How to size a server for your web app without overpaying
How to size a server using real CPU, memory, I/O and concurrency data, labelled rules of thumb, and a short k6 load-testing example.
On this page
Size a server for a web app by measuring its actual CPU, memory, disk I/O and concurrency under realistic load, not by picking a plan that "sounds about right" or matches what a similar-looking company uses. This post covers what to measure and how, a set of clearly labelled rules of thumb to start from, a short load-testing example using k6, the choice between scaling up and scaling out, and why sizing deserves a periodic review rather than a one-off decision. For the broader question of which server type to run this on, see the pillar guide, cloud servers explained.
Server sizing for a web app starts with measurement#
Before changing anything, look at what your app is actually doing:
- CPU. Is utilisation consistently high during normal peak periods, or only during rare spikes? Tools like
top,htoporvmstatshow this in real time; most hosting dashboards also chart it over time. - Memory. How much is genuinely used by your application and database versus available for caching, and is the server swapping to disk under load? Swapping is a strong signal you're short on RAM, not CPU.
- Disk I/O. Is storage keeping up, or are processes spending time waiting on it?
iostatand the%wa(I/O wait) figure intopare the standard places to look. - Concurrency. How many requests are actually in flight at the same time during peak periods, not just how many total requests you serve per day?
Concurrency deserves special attention because it's the one most people underweight. A slow endpoint — a report that takes eight seconds to generate, a badly indexed query — holds a connection, a worker process or a thread open for that whole time. A server can be overwhelmed by a fairly small number of concurrent users hitting a slow path, at a total request rate that looks unremarkable in an access log. Fixing the slow endpoint sometimes solves more than adding capacity does.
If you want a structured way to work through these four areas when something feels wrong rather than just when sizing upfront, Brendan Gregg's USE method — checking Utilisation, Saturation and Errors for each resource in turn — is a widely used framework for exactly this.
Labelled rules of thumb (starting points, not targets)#
These are starting points to measure from, not numbers to aim for. Every real app should be sized from its own measured data, using the rules below only to sanity-check a first guess before you have that data.
- Rule of thumb: start small and measure, rather than guessing large "to be safe." Oversizing wastes money quietly every month; undersizing at least tells you clearly, and quickly, that you need to adjust.
- Rule of thumb: keep meaningful headroom on memory — if a server is routinely near its full RAM under normal peak load, treat that as a warning sign, since the alternative to headroom is swapping, which is far slower than RAM and tends to make performance problems worse suddenly rather than gradually.
- Rule of thumb: databases usually benefit from more RAM before more CPU. More memory lets more of the working data set be cached instead of read from disk on every query, which often does more for perceived speed than an extra CPU core.
- Rule of thumb: watch I/O wait, not just CPU load. A server that looks "busy" but not overloaded on CPU, with response times still climbing, is often waiting on disk rather than short on processing power — a strong signal for NVMe storage or a differently configured disk, not necessarily more vCPU.
- Rule of thumb: size for your realistic peak concurrency, not your average. Average load tells you almost nothing about whether a server will cope with the ten minutes a day that actually matter.
Load testing with k6#
Rules of thumb only get you an educated starting point. Load testing tells you where your actual breaking point is, on your actual application, before your users find it for you. k6 is an open-source tool that scripts virtual users making requests against your app, on a schedule you define.
A short, complete example — ramping up to 50 simulated users, holding steady, then ramping down, with pass/fail thresholds:
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 50 }, // ramp up to 50 virtual users
{ duration: '5m', target: 50 }, // hold steady
{ duration: '2m', target: 0 }, // ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95% of requests under 500ms
http_req_failed: ['rate<0.01'], // fewer than 1% of requests fail
},
};
export default function () {
const res = http.get('https://your-app.example/');
check(res, { 'status is 200': (r) => r.status === 200 });
sleep(1);
}Run this with k6 run script.js. k6 reports whether your thresholds passed, along with response-time percentiles and the error rate — but the more important half of the exercise is watching your server at the same time, using the CPU, memory and I/O tools from the measuring section above. The k6 report tells you when things got slow or started failing; your server-side monitoring tells you why. Always run load tests against a staging environment that mirrors production, not production itself, unless you have a specific, carefully controlled reason to do otherwise.
Scale up vs scale out#
Once you know where the ceiling is, there are two ways to raise it:
Approach | How it works | Good for | Limitation |
|---|---|---|---|
Scale up (vertical) | Move to a server with more vCPU, RAM or faster storage | Simpler stacks, quick wins, apps not built for multiple instances | Has a ceiling; usually needs a resize or reboot |
Scale out (horizontal) | Add more servers behind a load balancer | Removing a hard ceiling; improving resilience alongside capacity | Needs an app that doesn't rely on server-local state; more moving parts to manage |
Scaling up is usually the right first move — it's a single change, with no code or architecture impact, and it buys time to plan properly. Scaling out is the right move once you've outgrown what a single machine can reasonably provide, or when resilience (surviving the loss of one server) matters as much as raw capacity. Moving to scale-out usually means addressing session state, file storage and background jobs so they don't assume "the app" is one specific machine — worth planning before you need it under pressure, not during an outage.
Cost tends to favour scaling up for longer than people expect. Running several smaller instances to match the capacity of one larger one is often not cheaper once you count the overhead of a load balancer, more operating systems to patch, and more surface area to monitor — the "overpaying" this post's title refers to is at least as often a case of scaling out too early as it is buying too large a single server. Let a genuine, measured need for resilience or a real ceiling on the biggest available single server drive that decision, rather than treating horizontal scaling as automatically the more modern or more correct architecture.
Right-sizing reviews: sizing isn't a one-off decision#
Traffic changes — gradually as a business grows, and suddenly around a launch, a campaign or a seasonal peak — so a size that was right six months ago isn't guaranteed to still be right. A reasonable habit is a quick check after any notable change in traffic or features, and a fuller review of utilisation trends every quarter or so, rather than only reacting once something is visibly struggling. This cuts both ways: it catches undersizing before it becomes an outage, and it catches overpaying for capacity that a growth spurt no longer needs, or never actually needed. Reviewing trends properly depends on having ongoing monitoring in place rather than checking in only when something feels slow, and it's exactly the kind of recurring task that tends to fall through the cracks without someone accountable for it — see managed vs unmanaged VPS for how that responsibility is usually split.
What to do next#
Once you have real numbers from measuring and, ideally, a load test, cloud servers covers the specifications available to match them, and current plans and prices lets you compare options at that size. If you're still deciding what type of server to size in the first place, VPS vs dedicated server vs cloud hosting is the right starting point.
Frequently asked questions
How do I know if my server is undersized?
Look for sustained high CPU utilisation, memory usage with little headroom (or swapping), rising disk I/O wait time, or response times that climb as concurrent users increase, rather than staying flat. One slow moment isn't proof; a consistent pattern across normal peak periods is. Measure with tools like top, vmstat and iostat over real traffic before concluding you need more capacity.
How much RAM does a web app need?
It depends entirely on your stack, your database's working set, and how many processes or workers you run — there's no single correct number. A small app might run comfortably in 1-2GB; a database-heavy app often wants considerably more RAM than CPU, since extra memory lets more data be cached instead of read from disk. Measure actual usage under real load rather than guessing from an install guide's minimum.
What's the difference between scaling up and scaling out?
Scaling up means moving to a bigger server — more vCPU, RAM or faster storage on the same machine. It's simple but has a ceiling and usually needs a resize or reboot. Scaling out means adding more servers behind a load balancer, which removes the ceiling and can improve resilience, but requires an application that doesn't rely on local, in-memory state tied to one server.
Is it safe to load test a production server?
Only with real caution. A load test is designed to push a system towards its limits, which can cause a genuine outage if run against production without warning. Test against a staging environment that matches production as closely as possible, and if you must test production, do it in a low-traffic window with the team on standby and a way to stop the test immediately.
How often should server sizing be reviewed?
A reasonable default is a quick review after any notable traffic change (a marketing push, a new feature, seasonal demand) and a fuller review roughly every quarter otherwise, checking utilisation trends rather than a single snapshot. This is one of the recurring tasks a managed service typically includes, rather than something done once at launch and forgotten.
Sources
- The USE Method — Brendan Gregg — accessed 18 September 2026
- Write your first test — Grafana k6 documentation — accessed 18 September 2026
- Thresholds — Grafana k6 documentation — accessed 18 September 2026
Facts in this article were last checked on 18 September 2026.
Inventure Engineering Team
Engineers at Inventure Technologies who build, host and run software for clients in Nepal and Australia. We write about what we do every day.
Keep reading
Cloud servers explained: VPS, dedicated servers and managed hosting (2026 guide)
Cloud server vs VPS vs dedicated server vs managed hosting, explained in plain English, with a decision table and a glossary.
Read articleManaged vs unmanaged VPS: what's included, and the hidden cost of DIY
What a managed VPS includes, what you do yourself on an unmanaged one, and a simple way to work out which is cheaper for your team.
Read articleVPS vs dedicated server vs cloud hosting: which does your business need?
An honest comparison of VPS, dedicated servers and cloud hosting, with a "not ideal for" case for each and a simple decision flow.
Read articleWant engineers who handle this for you?
We build, host and run software for teams in Nepal and Australia — with dedicated support on every plan.