When a site slows down under load, the instinct is to buy a bigger server. Sometimes that is right. Far more often the bottleneck is one unindexed query, and doubling the hardware buys you three months before the same problem returns at twice the cost.
Scaling has a correct order. Following it saves most teams a great deal of money.
Step 0: measure, because you are probably wrong
Do not optimise anything until you know what is slow. Every experienced engineer has spent a week speeding up something that was not the problem.
What you need before touching anything:
- Application performance monitoring. Which endpoints are slow, and where the time goes inside them.
- Slow query log. Turn it on. The answer is usually here.
- Server metrics. CPU, memory, disk input and output, connection counts.
- A real number. “It is slow” is not actionable. “The orders page takes 4.2 seconds at the 95th percentile, of which 3.8 is one query” is.
Step 1: fix the database
In our experience the majority of scaling problems in business applications are database problems, and most of those are one of three things.
Missing indexes
The single highest return fix in software. A query scanning two million rows becomes a query reading forty. Look at your slow query log, run the execution plan, add the index. Minutes of work, order of magnitude improvement.
The N plus one problem
Your code loads fifty orders, then loops and loads each customer separately. Fifty one queries where two would do. Every ORM makes this easy to write accidentally, and it is the most common performance bug in Laravel, Django and Rails applications. Eager load the relationship.
Selecting everything
Fetching every column and every row, then filtering in application code. Push the filtering into the query and select only the columns you use.
Related reading: database design mistakes that surface later.
Step 2: cache the expensive things
Only after the database is clean, because caching a slow query hides the problem rather than fixing it.
- Object caching with Redis for expensive computed results: dashboard figures, category trees, configuration.
- Full page caching for pages that are the same for everyone. This is what turns a struggling content site into a fast one, and it is usually a plugin or a server setting rather than a project.
- A CDN for images, CSS and JavaScript. Cheap, immediate, and it removes a large share of requests from your server entirely.
The rule that matters: decide how each cached thing gets invalidated before you cache it. Stale prices and stale stock levels cost more than slow pages.
Step 3: move slow work out of the request
Nothing that takes longer than a second should happen while a user waits. Emails, PDF generation, image processing, third party API calls, report building, bulk imports.
Put them on a queue and process them in a background worker. The user gets an immediate response, and a slow external service no longer takes your site down with it.
This one change often does more for perceived performance than any amount of extra hardware.
Step 4: scale up, then out
Scale up first. Doubling your server is simple, immediate and requires no architectural change. Modern hardware goes a very long way, and a well built application on one decent machine handles more traffic than most Pakistani businesses will ever see.
Scale out when you must. Multiple application servers behind a load balancer. This requires that your application be stateless, which means:
- Sessions in Redis or the database, not on the local disk
- Uploaded files in object storage, not the server filesystem
- No assumption that the same user hits the same machine
Make the application stateless early even if you never add a second server. It costs little and it is what makes everything later possible.
Step 5: scale the database itself
The hardest part, which is why it is last.
- Read replicas first. Send reporting and read heavy traffic to a copy. Handles the majority of cases.
- Connection pooling if you have many application servers competing for connections.
- Partitioning for very large tables, usually by date.
- Sharding only when genuinely unavoidable. It changes how you write every query and is rarely the right answer for a business application.
What to do at each stage
- Under 10,000 visits a day: one decent server, indexes in order, a CDN. That is the whole list.
- 10,000 to 100,000: add object and page caching, move slow work to queues, consider a read replica.
- 100,000 to a million: multiple application servers, load balancer, dedicated cache and queue, replicas.
- Above that: you have specific problems that need specific answers, and general advice stops helping.
Most businesses reading this are in the first two bands, and most of them can fix their performance problem this week without spending anything on infrastructure.
Frequently asked questions
My site is slow. What should I check first?
The slow query log, then whether your pages are cached, then image sizes. In that order. Hardware last.
Do I need microservices to scale?
No. Scale is rarely the reason to split an application, and doing so usually makes performance worse before it makes it better. See microservices versus monolith.
Will moving to the cloud make my site faster?
Only if your current hosting is the bottleneck, which is less often than assumed. The same slow query is slow everywhere. Our note on cloud hosting for Pakistani businesses covers when the move is worth it.
How much traffic can one server handle?
A well built application with caching on a modest cloud server handles tens of thousands of daily visitors comfortably. Poorly indexed applications struggle at a fraction of that, which is why the order in this article matters.
Ezitech builds and maintains platforms under real load for clients in 42 countries. If your application is slowing down, tell us what you are seeing and we will start by measuring rather than quoting hardware.
