Black Friday in the UK is less a day than a season. Traffic builds through the week, spikes hard on Thursday evening and again at Friday lunchtime, dips, then climbs for Cyber Monday. A store that copes comfortably on a normal Tuesday will not necessarily cope on the day. The work that makes the difference is unglamorous and well understood: model the traffic honestly, test it, cache aggressively, scale on the right signals, and rehearse what happens when something breaks. That is a few weeks of sensible preparation rather than a rebuild.
Model the traffic before you change any code
Most performance projects fail at the assumptions stage. Before you tune anything, write down what you expect to happen. If you ran promotions last year, pull the access logs and work out peak requests per second, peak concurrent users, and the split between cacheable browsing traffic and uncacheable cart, checkout and account traffic. That split matters more than the headline number.
Then talk to the people running the campaigns. Marketing knows when the email goes out, when the paid social budget switches on, and which affiliate placements are booked. Support knows which pages customers complain about. Add those events to your timeline. Also account for bots: stock checkers, scrapers and price comparison crawlers can add a noticeable slice of traffic that never converts.
You should end up with a short table: expected peak RPS, target p95 latency, acceptable error rate, and the hour each campaign lands. Everything after this is measured against it.
Load testing that tells you something useful
Hammering the homepage with a thousand virtual users proves almost nothing. Real journeys are messier.
- Script full paths: search, category listing, product page, add to basket, cart, checkout, payment callback, confirmation email.
- Use production-like data volumes. A catalogue with 200,000 SKUs behaves very differently from one with 2,000.
- Set a realistic think time between steps. Customers read, compare and hesitate; they do not fire requests back to back.
- Ramp beyond expected peak. You are looking for the point where latency bends upwards, not just a pass or fail at your target.
- Run from outside your own network. Your office connection is not the internet.
- Keep session state, cookies and logged-in journeys in the mix, because that is where caching stops helping.
Tools such as k6, Gatling, Locust and JMeter all do this well; the tool matters far less than realism. Where possible, test against a cloned environment behind the same CDN and WAF configuration as production, and re-run the test after every significant change so you know which fix actually helped.
Caching, from the edge inwards
Most Black Friday traffic is people looking at things they will not buy. That traffic should never reach your application servers.
At the edge, serve static assets with long cache lifetimes and hashed filenames, and cache HTML fragments where personalisation allows. The usual culprits that quietly destroy hit ratios are session IDs in URLs, unnecessary query strings, marketing parameters and cookies set on every response. Audit them.
Behind the CDN, put sessions, baskets and catalogue fragments in Redis or Memcached with sensible expiry, and invalidate deliberately when prices or stock change. For heavy listing pages, consider materialised views or pre-computed result sets rather than expensive queries run per request.
Watch out for cache stampedes: when a popular key expires, hundreds of requests can hit the database at once. Request coalescing, jittered expiry times and stale-while-revalidate responses are all cheap defences. Measure hit ratio per route rather than as a single overall figure, otherwise the checkout will drag down an otherwise healthy number and hide the page that is actually struggling.
Auto-scaling on the right signals
CPU is a lagging indicator for web tiers. By the time it climbs, latency has already gone. Scale on requests per target, queue depth or p95 latency instead, and combine them with a sensible floor of capacity rather than scaling from the minimum.
Pre-warm before the sale. Check how long a new instance takes to serve its first request properly: container image pulls, connection pool establishment and framework warmup all add delay. Then scale the parts people forget: read replicas for the database, connection pooling in front of it, and cache cluster capacity.
Two practical checks worth doing in advance: confirm your cloud quotas allow the instances, IP addresses and load balancer capacity you plan to use, and make sure your scaling policies have cooldowns. Aggressive up-and-down behaviour during a spike can cause more trouble than it solves.
Protect the checkout and the database
The checkout is the only part of the site that takes money, so design it to fail gracefully. Keep transactions short, never make external calls inside a database transaction, and use idempotency keys on order creation and payment requests so a retry does not create a duplicate order.
Push everything non-essential into a queue: confirmation emails, stock synchronisation, loyalty points, ERP updates. Put rate limiting and bot rules at the edge, but test them on mobile first — an aggressive challenge hurts conversion more than a slow page. When load does exceed capacity, a clear "we are busy, please try again in a moment" is far better than a thirty-second timeout.
Audit third-party scripts too. Analytics, chat widgets, reviews and testing tools all compete for the same browser and can wreck your Core Web Vitals during the busiest hour. Load the essential ones, defer the rest. If you have negotiated higher payment provider limits for the peak, confirm them in writing.
Monitor, alert and rehearse failure
Put business metrics on the same dashboard as technical ones: orders per minute, payment success rate and checkout abandonment next to error rates and latency. Those are the numbers that tell you whether an incident is actually happening.
Alerts should be few and actionable. A noisy alert channel is worse than none, because people stop reading it. Agree an on-call rota, an incident channel and a short runbook covering the most likely failures and who to escalate to.
Then rehearse. Kill an instance, drop a cache node, add latency to a dependency, and watch how the system and the team respond. Test a restore from backup rather than assuming it works.
A workable countdown
Six weeks out: model traffic, fix obvious performance problems, book a load test. Four weeks: run the test, tune caching, plan capacity, check cloud quotas. Two weeks: re-test, freeze non-essential changes, brief support and marketing on expected peaks. Sale week: monitor closely, hold spare capacity, keep changes small, and have a rollback ready.
Budget for headroom, because you will pay for capacity you may not use. That is almost always cheaper than an outage on the busiest weekend of the year. The goal is not an impressive-looking architecture; it is a dull, predictable Friday where nothing in your inbox is on fire.
Photo: Preis_King / Pixabay




