How do apps handle massive traffic spikes like Black Friday without breaking?
Quick answer: handling a traffic spike like Black Friday means balancing headroom against cost — auto-scaling rules that add capacity ahead of predicted demand (not reactively, once it's already struggling), caching aggressively at the edge to keep load off origin servers, and load testing at realistic peak volume beforehand so the first time the system sees that traffic isn't the day it actually matters.
Hi, I'm Neil, a DevOps expert, and today I'm going through the Black Friday challenge — that time of year in e-commerce that's high traffic and resource intensive, where you've got to balance high turnover against the high cost of cloud resources. Let's go through the steps: planning, real-time monitoring, autoscaling in action, and financial controls.
Pre-planning
We can look at last year's stats — how busy was the website last year? Analyzing the previous Black Friday's traffic helps us understand what might happen this year. We can run load tests against the app in a pre-production or dedicated performance environment, to see how much traffic we can throw at it before it breaks — that gives an indication of where a bottleneck is, or where a bug fix could make things go faster. We can calculate the resources required to run at specific levels, and therefore how much it's going to cost, and use this data to set thresholds so we know when things are getting busy — and of course we can use GitOps to help set all this up.
Real-time monitoring
Once we're in the Black Friday period, we should be monitoring so we have a clue what's going on. Key metrics to watch:
- Request times and request rates — how many requests we're getting per second (or smaller units for a really big site), so we understand what's going on with our servers. Each request will also have a response code, delivered after a certain response time, so we can see how long requests take and what code results. Most of the time it'll be a 200, meaning everything went fine — if we get errors, we should track those, since an error might be a bug or a bottleneck somewhere else.
- CPU and memory usage — adding more CPU or memory might help next year, or right now if we've got autoscaling set up (more on that below).
- Error rates — some errors are expected at a certain baseline level, because stuff always breaks, and you need to be ready for that. Error rates can spike when a specific microservice is hit, or when the database slows down, or something else — as they increase, they give us more data to make the system better next time.
- Cost — while the system is running, we can work out cost per hour, per minute, or even per request. This gives us information to plan later, or to make a real-time decision about whether we need to scale immediately.
Autoscaling in action
There are two types of scaling: horizontal and vertical. Horizontal scaling is where we take the same cookie-cutter process — a server, a virtual server, a container — and stamp out more of them, so we can go from two servers to four to eight to however many it takes for the workload. Vertical scaling is where we make the resource itself bigger — give that virtual server more memory or more CPU. There are pros and cons depending on where you are and what layer needs fixing — it's quite common for web or proxy servers to scale horizontally, and for database servers to scale vertically, and of course you can blend the two.
For scaling policies, we want to know when to scale up, and more importantly when to scale down. You might have a policy that says "CPU usage above 70% for 5 minutes, scale up horizontally, add another unit to the server farm," and then scale down again if it drops to, say, 10% CPU usage. But don't be fooled — that sentence hides a lot of complexity. Scaling down is hard — what do you do if there's a request already in flight? Make sure that node isn't handling any traffic before you kill it. The other gotcha is you don't want to be flapping — scaling down, then up, then down, then up — so you want a scale-down cool-off period to make sure the spike has really gone, and you're not just idle for a few seconds.
While we're talking about load and scaling, have you thought about regional distribution? Some providers let you put servers closer to the customer — if you're in the US, servers on the West Coast and more on the East Coast, distributed to match where the traffic is.
Financial controls
Scaling up costs more money, so we want cost monitoring and cost alerts in place — this lets us understand how much we're spending in real time, and whether we're spending too much or too little against our forecasts. Alerts tell us when we hit certain thresholds, and our configuration will usually have a maximum already defined — a system alert that says "scale up until you hit a maximum of 32 instances," and at that point it doesn't matter if CPU is still above 70% for 5 minutes, don't scale up any further. Sometimes that's okay — a customer hits the limit, sees "sorry, we're busy, try again in 5 minutes," and for your business that might be an acceptable trade-off.
Another way to control costs is paying upfront for a discount — if we know we're going to be busy and use a certain amount of resources, will our supplier give us a discount for money up front? In AWS this is called reserved instances — you reserve an instance up to a specific amount of usage (all day, or half the day) for a specific term (1 month, 3 months, a year, 3 years), depending on the expected workload. For particularly spiky traffic or short durations, spot instances can be useful — much cheaper than on-demand pricing, but very temporary, and can be shut down with two minutes' notice. Finally, tag your resources so you can attribute cost to a specific project, which lets you analyze costs further.
Pro tips and best practices
- Don't optimize first — load testing is your friend. Run the load tests, find out what actually needs optimizing, then optimize it. Don't guess, you're wasting time — find the limits and bottlenecks, and that tells you what to optimize.
- Some things are too expensive to scale, like an Oracle database that charges per CPU — that's a lot of backend cost just for a temporary change. Maybe there's a better way, like adding a caching layer (a query cache in front of the database), or putting things into a queuing system so they can be processed later, once the system catches up.
- Understand your budget — scaling will cost money, so you need to know how much budget you have to set those top limits.
- Traffic management — sometimes it's okay to put a customer in a queue and make them wait a little longer, if you're hitting the top limits of your resources.
- Top tip: don't deploy changes to your infrastructure at peak times, even if it's struggling — resist the urge to change anything, or you might give yourself proper downtime during the event.
Once the event is over and the dust has settled, make sure everything has scaled back down — you don't want to keep paying for capacity you're not using. Review the effectiveness of the scaling you had in place, particularly around error rates, and analyze the costs: how many transactions did you do, how much did it cost you to do them, was it worth the extra cost? Only your business can tell you that.
I hope that gives you a great idea of what you can do about the Black Friday chaos coming up in a couple of weeks. If I can help in any other way, reach out, and I'll see you next time — may all your deployments be smooth.