Mar 22, 202612 min read
Scalable Infrastructure: What Happens When Traffic Suddenly Spikes
Learn how scalable infrastructure handles traffic spikes using load balancing, autoscaling, CDN, caching, queues, database scaling, rate limiting, observability, and load testing.

Everything looks normal.
The site is fast.
CPU usage is low.
The database is healthy.
Then something changes.
A campaign goes live.
A product goes viral.
A message is sent to hundreds of thousands of users.
A sale starts.
Or a news event suddenly drives traffic up within minutes.
Response times increase.
Database connections fill up.
Queues grow.
Some users start seeing errors.
The first reaction is usually:
We need a bigger server.
Sometimes that is true.
But in many systems, a bigger server only pushes the failure point a little further away.
Scalable infrastructure is not infrastructure that never comes under pressure.
It is infrastructure that can add capacity when demand grows, distribute load across components, and, when demand exceeds the final available capacity, degrade in a controlled way instead of collapsing completely.
Microsoft recommends designing cloud applications for horizontal scaling wherever practical: adding instances as demand grows rather than depending entirely on increasingly powerful individual machines.
So the real question is not:
“How powerful is our server?”
A better question is:
“If traffic increases fivefold, which part of the system fails first?”
Know Your Real Capacity Before You Scale
If you do not know how much traffic your system can handle today, you cannot plan intelligently for tomorrow.
You need a baseline.
At minimum, understand things like:
- Requests per second
- P50 / P95 / P99 latency
- Concurrent users
- CPU usage
- Memory usage
- Database connections
- Disk IOPS
- Queue length
- Error rate
- And the point at which performance begins to degrade
This gives you a capacity baseline.
Google SRE guidance recommends measuring the relationship between resources and capacity through load testing rather than relying on assumptions.
For example:
Four servers handled 4,000 requests per second six months ago.
That does not mean they still can after several new features, heavier queries, and additional integrations.
Capacity is not something you measure once and remember forever.
Scale Up or Scale Out?
There are two basic ways to add capacity.
Vertical Scaling — Scale Up
Give one machine more resources.
- More CPU
- More RAM
- A larger instance
- A faster GPU
Horizontal Scaling — Scale Out
Add more instances and distribute traffic between them.
For many cloud workloads, horizontal scaling offers more flexibility because capacity can increase or decrease dynamically with demand.
But there is a condition:
The application must actually support scale-out.
If user sessions live only in local server memory, adding another instance can create problems.
If every request must return to the exact same server, load balancing becomes less flexible.
If all instances constantly wait on the same shared resource, adding more instances may not improve throughput much.
That is why keeping the application layer as stateless as possible is an important part of scalable architecture.
A Load Balancer Distributes Capacity. It Does Not Create It.
Once you have multiple instances, requests need to be distributed across them.
That is where a load balancer helps.
Load balancing can:
- Spread traffic between backend instances
- Improve resource utilization
- Remove unhealthy servers from rotation
- Support redundancy
- Avoid sending all traffic to one machine
But there is an important limitation:
If all of those application servers depend on one shared bottleneck, the bottleneck still exists.
Imagine you have ten application servers.
They all connect to one undersized database.
The application layer has scaled.
The database has not.
In that case, the load balancer simply helps you reach the next bottleneck faster.
Not Every Request Should Reach the Origin
One of the most effective ways to survive high traffic is to avoid sending every request to the application in the first place.
A CDN can serve static and cacheable content from edge locations closer to users.
That may include:
- Images
- CSS
- JavaScript
- Downloads
- Media
- And sometimes cacheable application responses
AWS CloudFront documentation explains that a higher cache hit ratio reduces the number of requests the origin needs to handle, which can reduce both latency and origin load.
Imagine 100,000 users opening the same product page during a promotion.
If every image request reaches the application server and central storage, the origin is doing work that an edge cache could have handled much more efficiently.
The best request for your origin is the request that never needs to reach it.
Caching Is Not Only for Static Files
Application-level caching can also remove expensive repeated reads from databases and backend services.
Imagine every product-page request needs to fetch:
- Category information
- Configuration
- Reference data
- Heavy aggregation queries
- Or frequently reused product metadata
If thousands of users request nearly identical information within seconds, running the same database query every time is expensive.
The Cache-Aside pattern is one common approach.
The application checks the cache first.
If the value exists, it uses it.
If not, the application queries the data store and then places the result into cache for future requests.
But cache introduces its own design questions:
- How long should data live?
- How is it invalidated?
- Can stale data be tolerated?
- What happens during cache failure?
- Can sensitive data be cached safely?
The goal is not:
Cache everything.
The goal is:
Remove expensive, repetitive reads from the critical path where the consistency requirements allow it.
Not Every Task Needs to Finish Inside the Request
One of the reasons systems collapse under load is that every incoming request tries to complete every downstream task immediately.
Imagine a user places an order.
The request then waits for:
- Order creation
- PDF generation
- Email delivery
- SMS delivery
- CRM synchronization
- Accounting synchronization
- Analytics updates
Several of those tasks probably do not need to finish before the user receives confirmation.
They can be asynchronous.
The core operation completes first.
Additional work enters a queue.
Workers process it at a rate the backend can safely handle.
Microsoft describes this as Queue-Based Load Leveling.
The queue becomes a buffer between a sudden burst of incoming work and the slower backend that processes it.
Imagine 20,000 orders arrive within 30 seconds.
You probably do not need to send 20,000 confirmation emails in the same 30 seconds.
The order needs to exist.
The email can arrive a few seconds later.
That difference can prevent a burst from turning into a cascading failure.
The Database Will Eventually Tell You Where the Limit Is
Application servers are often relatively easy to scale horizontally.
Databases are more complicated.
Under heavy traffic, the problem may not even be CPU.
It may be:
- Connection pool exhaustion
- Lock contention
- A slow query
- Missing indexes
- Storage IOPS
- Replication lag
- A table scan
- Or hundreds of application instances executing the same expensive query
So before simply making the database larger, find the actual bottleneck.
For read-heavy workloads, read replicas can help move query traffic away from the primary database.
AWS documents this pattern for RDS: replicas can serve read traffic while the primary continues handling writes.
But replication is often asynchronous, so some amount of lag may exist.
For different systems, the right answer may be:
- Caching
- Read replicas
- Partitioning
- Sharding
- Query optimization
- Indexing
- Or a different data model
And very often, the first useful step is simply fixing bad queries.
Scaling the database before optimizing it can just make an inefficient query more expensive.
Connect Autoscaling to the Right Metric
Autoscaling means the system changes capacity based on demand.
But what should trigger that change?
CPU is a common metric.
It is not always the best one.
Imagine CPU is low, but the request queue keeps growing.
Or application CPU looks healthy while database connections are almost exhausted.
For workers, queue length may be more meaningful.
For web servers, requests per instance may be better.
For other workloads, latency or concurrent requests may tell the story more accurately.
AWS target tracking can scale based on metrics such as CPU or requests per target, while Azure autoscaling guidance also supports metrics such as queue length.
The important principle is:
The scaling metric should reflect the real bottleneck.
Not simply the number that is easiest to put on a dashboard.
Autoscaling Is Fast. It Is Not Instant.
This matters a lot during traffic spikes.
When the threshold is crossed, the platform decides to create more capacity.
But new capacity still needs time.
An instance may need to:
- Start
- Load the application
- Initialize dependencies
- Connect to external services
- Pass health checks
- Warm caches
- Then begin receiving traffic
This is why cloud platforms include concepts such as warm-up periods and warm pools.
If your system supports 1,000 requests per second and traffic jumps to 10,000 within two seconds, autoscaling alone may not react quickly enough.
This is where several techniques need to work together:
- CDN
- Cache
- Queues
- Base capacity
- Autoscaling
- And load shedding
If You Know the Spike Is Coming, Scale Before the Users Arrive
Not every traffic spike is unpredictable.
You may already know:
- A sale begins at 10:00
- A marketing message goes out at 18:00
- Registration opens at a specific time
- A livestream starts at a known hour
In these situations, waiting for CPU to increase before adding capacity is unnecessary.
You can pre-scale.
Scheduled scaling is especially useful for predictable demand patterns.
When the event matters, a few minutes of excess capacity is usually cheaper than a few minutes of downtime.
Do Not Set Minimum Capacity Too Low
Scale-to-zero or extremely low baseline capacity can reduce cost.
But it is not always appropriate for latency-sensitive services.
When traffic arrives, the system needs some capacity from which to scale.
So minimum capacity should reflect:
- Risk
- Latency requirements
- Expected burst size
- Warm-up time
- SLOs
Unused capacity costs money.
Insufficient capacity also costs money.
The objective is not the lowest infrastructure bill possible.
It is the lowest cost that still protects the required service level.
Different Components Need Different Scaling Policies
A real system may include:
- Frontend
- API layer
- Background workers
- Search
- Image processing
- Recommendation services
- Database
- Cache
- Queue consumers
Each behaves differently.
The API layer may need to scale immediately when users arrive.
Background workers may be able to process a backlog over several minutes.
Search may have different memory requirements.
Image processing may be CPU or GPU bound.
That means one scaling rule for the entire platform is usually too simple.
A good architecture allows each bottleneck to scale according to its own demand.
Rate Limiting Is Not Only a Security Tool
Even completely valid users can overload a system.
If one client can send 10,000 requests per second, the result may look very similar to an attack.
Rate limiting and throttling help control consumption.
Limits can be based on:
- User
- IP
- API key
- Tenant
- Operation
- Endpoint
- Plan level
- Or request cost
A lightweight GET request and a heavy report-generation request should not necessarily share the same limit.
Microsoft’s throttling guidance treats overload as a normal system state that should be managed intentionally.
The important idea is:
Do not wait for the system to fail before deciding how much traffic is too much.
When Capacity Runs Out, Do Not Let Everything Fail Together
No infrastructure has infinite capacity.
Eventually, demand can exceed what the system can safely process.
At that point, behavior matters.
A fragile system tries to accept everything.
Latency increases.
Timeouts increase.
Clients retry.
Retries create more traffic.
Dependencies slow down.
The problem spreads.
A capacity issue becomes a cascading failure.
Google SRE recommends shedding load or providing cheaper fallback responses when the system is overloaded.
This is graceful degradation.
During extreme traffic, you might temporarily:
- Disable personalized recommendations
- Serve cached data
- Queue heavy reports
- Reduce image quality
- Return simpler search results
- Limit non-critical background work
- While keeping checkout or core transactions alive
This is not only a technical decision.
It is a business decision:
Which capability must stay available even when the system is under extreme pressure?
Retry Can Become an Attack From Your Own System
Imagine a backend becomes slow.
Every client times out and immediately retries.
Now the backend has to process:
- Original traffic
- Plus retry traffic
That increases latency further.
More timeouts happen.
More retries follow.
Google SRE warns that uncontrolled retries can amplify small failures into cascading failures.
Better retry strategies include:
- Exponential backoff
- Jitter
- Retry limits
- Retry budgets
- And only retrying operations that are actually safe to retry
Retry should mean:
Try again intelligently.
Not:
Keep hitting the broken service until it comes back.
Scalability and Availability Are Not the Same Thing
A system may handle enormous traffic and still have a single point of failure.
Imagine 20 application instances.
They all run in one availability zone.
If that zone fails, the number of instances does not help.
For critical workloads, redundancy needs to be designed alongside scalability.
That may include:
- Multiple instances
- Multiple availability zones
- Database replicas
- Redundant load balancers
- And, for some workloads, multiple regions
The distinction is simple:
Scalability asks: How much demand can we handle?
Reliability asks: If part of the system fails, do we keep working?
They are related.
They are not the same problem.
Observability Needs to Exist Before the Spike
A traffic incident is the wrong time to ask:
How do we figure out what is slow?
Before production, you should already have:
- Metrics
- Logs
- Distributed traces
- Alerts
- Dashboards
A high-traffic dashboard should show more than CPU and RAM.
You should be able to follow the chain:
Traffic increased.
P95 latency increased.
Cache hit ratio dropped.
Database connections increased.
A query became slow.
Queue backlog grew.
Autoscaling added instances.
Error rate returned to normal.
That is what observability should give you.
Knowing:
CPU is at 90%
is useful.
Knowing why is much more valuable.
Averages Can Hide the Real Problem
Imagine average response time is 250 ms.
That sounds good.
But maybe 95% of users get 150 ms responses while the remaining 5% wait three seconds.
At high scale, that 5% can represent a very large number of unhappy users.
This is why percentile metrics matter.
Useful latency measurements include:
- P50
- P95
- P99
Average latency is still useful.
It just should not be the only number.
For high-traffic systems, tail latency often tells you where the real experience problem is.
Load Test Until the System Struggles
A load test that only covers normal traffic does not tell you much about crisis behavior.
A good load test should answer questions like:
- At what RPS does the system stop meeting the SLO?
- What is the first bottleneck?
- How long does autoscaling take?
- When does latency increase sharply?
- How much queue backlog can the system tolerate?
- Does the service degrade gracefully or collapse?
- Can the system recover when traffic drops again?
Google SRE recommends testing both capacity limits and failure behavior under overload.
The goal of load testing is not to prove:
Our system is fast.
The goal is to learn:
Where does it break, and what happens when it does?
What Does a High-Traffic Architecture Usually Look Like?
There is no universal design, but a common flow might look like:
User → DNS / CDN → WAF / Gateway → Load Balancer → Stateless Application Instances → Cache / Queue → Databases & Services
Around that, you may also have:
- Autoscaling
- Monitoring
- Distributed tracing
- Centralized logging
- Rate limiting
- Health checks
- Backup
- Multi-zone redundancy
- Alerting
The important part is not having every technology on the list.
It is making sure every component solves a real problem.
If your system serves 200 users per day, adding Kubernetes, five regions, and ten microservices may technically look scalable.
It may also be completely unnecessary.
Architecture should match real demand, not the number of tools you can put in a diagram.
A Practical Traffic Spike Checklist
| Area | Main Question |
|---|---|
| Capacity | How much load can the system handle while meeting its SLO? |
| Bottleneck | Which resource saturates first? |
| Application | Can the application layer scale horizontally? |
| Load Balancing | Is traffic distributed only across healthy instances? |
| CDN | How much traffic can be served before reaching the origin? |
| Cache | Which expensive reads can be removed from the database path? |
| Async Work | Which operations do not need to finish inside the user request? |
| Queue | Can bursts be buffered safely? |
| Database | Are queries, connections, indexes, and read scaling ready? |
| Autoscaling | Are the right metric and min/max capacity configured? |
| Warm-Up | How long does new capacity take to become ready? |
| Pre-Scaling | Is the peak predictable enough to scale in advance? |
| Throttling | How does the system protect itself from excess demand? |
| Degradation | Which features can become simpler during overload? |
| Retry | Do clients use backoff, jitter, and retry limits? |
| Reliability | Where are the single points of failure? |
| Observability | Can you identify the bottleneck within minutes? |
| Load Testing | Has the system been tested beyond normal capacity? |
| Recovery | Does the system return cleanly to normal after the spike? |
Does Scalability Mean Infinite Capacity?
No.
No system has infinite capacity.
Even the largest platforms have:
- Budgets
- Quotas
- Bottlenecks
- Physical limits
- Failure modes
The goal of scalable architecture is not to say:
“We can handle any amount of traffic.”
The goal is to know:
- What your current capacity is
- How you add more capacity
- Which components scale independently
- Which alerts appear before saturation
- And what happens when demand exceeds the final safe limit
A bigger server can be part of the answer.
But truly scalable systems are usually built through a collection of smaller decisions:
Requests that do not need the origin are cached.
Work that does not need to happen immediately enters a queue.
Traffic is distributed across multiple instances.
Capacity follows demand.
The database is scaled and optimized separately.
And when capacity really runs out, the system knows how to say “no” without taking everything else down with it.
Good infrastructure is not only fast when things are quiet. It knows how to stay calm when everyone arrives at once.
Related services
Related articles
Sources & further reading
- Microsoft Azure Architecture Center — Scale-Out Design Principles, Autoscaling, Queue-Based Load Leveling, Cache-Aside, and Throttling
- AWS Documentation — EC2 Auto Scaling and Target Tracking
- AWS Documentation — CloudFront Caching and Origin Shield
- AWS Documentation — RDS Read Replicas
- Google Site Reliability Engineering — Handling Overload and Cascading Failures
- Kubernetes Documentation — Horizontal Pod Autoscaling