HomeResourcesCase study
Case study

Pinterest's Cache Survived 180M req/s — Until a Deploy

By The SDL team·4 min read·Updated Sep 16, 2026

The thundering herd you've heard of is about cache misses. The one that took Pinterest down was about reconnections.

Pinterest's caching fleet handles 180 million requests a second. It wasn't a traffic spike that knocked it over. It was deploying a routine software update — the most controlled event in all of operations.

The cache is enormous: over 5,000 servers, ~180M requests/sec, ~220 GB/s of throughput across a ~460 TB dataset in roughly 70 clusters. And when they rolled out a new memcached binary — a normal, planned deploy — clients started getting connection-refused errors in spikes. The problem wasn't load. It was the restart itself.

Plain English

When you update software on a server, you restart the program. For a brief moment, it's not listening. All its clients — here, thousands of routing processes — notice the connection dropped and immediately try to reconnect. At the same instant. That synchronised stampede is a thundering herd.

A freshly restarted server has a small waiting room for incoming connections (the "accept queue"). Thousands of simultaneous reconnections overflow that waiting room, and the server starts refusing connections outright — which the clients read as an error. You caused an outage by doing the safest thing you do all week.

Where the herd actually trips

The specific mechanism: every TCP server has a kernel-level accept queue — connections that have completed the handshake and are waiting to be picked up by the application. Its size is capped by a setting called net.core.somaxconn and the listen backlog. Under a reconnect storm, the queue fills faster than memcached can drain it, the kernel rejects the overflow, and clients see ECONNREFUSED. The default queue size was simply never meant for thousands of simultaneous reconnects.

A deploy, not traffic, caused the outage: the accept-queue overflow thousands of mcrouter clients reconnect at once SYN flood memcached (just restarted) TCP accept queue FULL → somaxconn too low ECONNREFUSED Fix 1 — raise net.core.somaxconn / listen backlog: a bigger accept queue absorbs the reconnect burst instead of refusing it. Fix 2 — run memcached on the real-time scheduler (SCHED_FIFO): the network thread stops getting pre-empted under load. Client p99 dropped 10–40%, shaving ~10% off the fleet’s total cost.
The deploy-time thundering herd. A restart triggers mass reconnection; the default accept queue overflows; clients get connection-refused. Two kernel-level fixes, not application code.
Now the engineering

The first fix is mundane and powerful: raise the accept queue size (net.core.somaxconn and the listen backlog). A larger queue absorbs the reconnect burst rather than refusing it, giving memcached time to work through the backlog. No application change — a kernel parameter that the defaults got wrong for this scale.

The second fix is the one that shows real systems depth. Pinterest moved memcached onto the Linux real-time scheduler (SCHED_FIFO). Normally the OS scheduler can pre-empt memcached's threads to run other work; under load, that means the network thread gets interrupted at exactly the wrong moments, adding latency. Real-time scheduling keeps the critical thread running. The result: client-side p99 latency dropped between 10% and 40%, and because each server now did more useful work per unit of hardware, it shaved close to 10% off the fleet's total cost.

180M/s
requests served
10–40%
p99 latency reduction
~10%
fleet cost saved

Worth knowing

Notice where every fix lived: the kernel, not the code. The application was fine. The bottleneck was in the operating system's defaults — accept-queue sizing and thread scheduling — which are tuned for a generic server, not for one fielding 180 million requests a second. At extreme scale, the layer you've been ignoring becomes the layer that matters.

The gap it reveals

Most engineers stop at "the cache handles reads." They've never considered that deploying a cache can take it down, that the failure lives in the TCP accept queue, or that the OS scheduler is a tunable performance lever. Knowing that the thundering herd applies to reconnections (not just cache misses), and that the fixes are kernel parameters, is the kind of depth that only comes from operating at a scale where defaults break.

In the interview room

If your design leans on a large cache fleet, a deep interviewer may probe: "how do you deploy a new version without an outage?" Strong signals include staggered/rolling restarts, connection draining, and an awareness that mass reconnection is itself a load event the accept queue must absorb. Mentioning somaxconn unprompted is a flex that lands.

The reframe

We obsess over the steady state — requests per second, cache hit rate — and forget that the transitions are where systems break. A deploy, a restart, a failover: these are moments of synchronised behaviour, and synchronisation is the enemy of stability. Pinterest's lesson is that at scale, you must design the transitions as carefully as the steady state, and that the answers often live one layer below your application.

The traffic didn't break it. The reconnection did. Mind the transitions.

Primary source →
pinterest-engineering — Improving Distributed Caching Performance and Efficiency at Pinterest

Want feedback on your design?

The weekly teardown

One real-world architecture, every week.

How real companies actually built it: the design, the trade-offs, and what to say about it in an interview. Free, and one click to unsubscribe.

Related articles