
Direct client-to-database connections at massive scale create an unbounded many-to-many mesh, leading to severe connection exhaustion, database crashes, and cascading failures.
- Proxy Interposition: Deploy ZGateway to terminate TLS, multiplex connections, and strictly bound database fan-in.
- Request Coalescing: Batch and merge requests across unrelated client fleets to fetch hot keys once and prevent thundering herds.
- Tenant Isolation: Enforce discriminant load shedding to drop excess traffic from misbehaving clients while preserving healthy workloads.
Adds a network hop, incurs about six percent computational overhead, and introduces the operational complexity of managing an entirely new infrastructure tier.
Script
Why Meta Intentionally Slowed Down Its Fastest Database
Meta deliberately made their fastest key-value store slower. They added a network hop. Billions of operations per second now flow through a proxy layer called ZGateway before they hit ZippyDB. And they did it on purpose.
Picture this. It's Tuesday morning. Your deploy pipeline is green. Traffic looks normal. Then your database hosts start falling over. Not from heavy queries. From connection exhaustion. A client fleet restarted. Every instance opened fresh TLS connections to tens of thousands of shards. File descriptors ran out. Hosts crashed. They rebooted. They reconnected. They crashed again. The fleet entered a loop.
This is not theoretical. Meta traced exactly this kind of incident to direct client access at scale. When a million hosts talk to half a million database hosts, you get a dense many-to-many mesh. A single client can hold tens of thousands of outbound connections. Add another client cohort, and every database host gets worse.
The instinct is to fix the clients. But you can't. Those clients belong to hundreds of teams. Their release cycles are not yours. Changing a million binaries is not a Tuesday morning activity. So Meta interposed a proxy. ZGateway sits between the clients and ZippyDB's database hosts. It terminates TLS, batches requests, enforces per-tenant quotas, and balances load across its own tier. It adds about six percent computational overhead. It also collapses per-host connection counts by roughly ninety-seven percent.
The connection counts don't vanish. They move to the tier built to hold them. Each backend connection multiplexes many clients. End to end, total persistent connections drop by roughly nineteen times. But the numbers are not the point. The scaling behavior is.
Under direct access, database fan-in grows linearly with your client population. Every new service makes every database host slightly worse. With ZGateway in the path, the client population drops out of the equation. Fan-in becomes bounded by the proxy fleet size and shard density. An unbounded number driven by everyone else becomes a bounded number you control.
The Proxy Advantage: Caching, Batching, and Resilience
ZGateway also does what no client library can. It batches and coalesces requests across unrelated callers. If a thousand clients ask for the same hot key in the same millisecond, the gateway fetches it once and fans the result out. A client-side library can only merge its own process's requests. The gateway merges them across the fleet. Requests park in an in-memory batch that flushes on a timer, a size limit, or a count cap. Oversized or freshly-migrated batches fall back to individual sends. There is idle eviction for slow-burn memory growth and an in-flight cap for acute overload. Without those guardrails, batching would be a denial-of-service tool. With them, it is safe by default.
The proxy also hosts read caching with live invalidation. A change-data-capture stream of write events invalidates entries within a bounded staleness contract. Hot reads serve from memory without touching storage. And because the gateway holds a per-key fill lock, a thundering herd for one key collapses into a single backend fetch.
Cross-region resilience is another capability that only works from a shared vantage point. For most of its life, ZGateway stayed strictly regional. But when an entire region's tier saturates, requests queue and die locally while healthy capacity sits idle next door. Now ZGateway can fail over across regions in a controlled way. Global routing tables span regions. Mega-regions group nearby localities. Rings declare exactly which regions back each other up, and in what proportion. Each mechanism hides behind the same percentage knob. Nothing is all-or-nothing.
There is also a subtler point about client thickness. ZGateway runs Meta's thick C++ client as its engine. Historically, transaction bookkeeping lived in that thick client. When Meta moved customers to a thin client, that logic had to land somewhere. It landed on the gateway. That consolidation means the most correctness-critical path evolves once, inside the tier, and every client inherits it. The alternative is two parallel implementations drifting apart.
When a Proxy Is a Liability
But here's the part that should make you nervous. ZGateway is another tier. Another hop. Another thing to operate, debug, and wake up for. The article admits this explicitly. Direct access was the right design for the first phase of ZippyDB's life. At smaller scale, the mesh is merely inefficient. At massive scale, it becomes a reliability limit.
Building the proxy earlier would have meant building the prerequisites first: service mesh integration, overload protection, a thin client. The means arrived on the same schedule as the need.
This is crucial. Don't add a proxy because Meta did. Add it when the cost of not having one exceeds the cost of operating it. So who actually needs this? If you control all your clients, if your team owns every binary in the path, and if you can roll out a library change in hours, you probably don't need a gateway tier yet. The complexity is not free. A proxy centralizes problems, which is only helpful if you have a team ready to own that centralized pain. If your client population is large, diverse, and not yours to change, the math flips.
From Chaos to Control
When hundreds of teams depend on your database and you cannot coordinate their behavior, a proxy becomes structural. It is the only place where you can see the whole workload, attribute load to specific tenants, and change behavior in minutes instead of waiting out a fleet-wide rollout.
The admission control story makes this concrete. ZGateway uses discriminant load shedding. Requests sort into per-tenant buckets. When one tenant floods the tier, its own bucket fills and its excess gets dropped. The other thirteen-hundred-plus tenants keep running. In a controlled overload above ninety percent CPU, only six tenants shed load. The rest executed ninety-nine point nine percent of their requests with zero rejections. Goodput stayed near ninety-seven percent. You cannot get that property from a client-side fix. Not when the clients don't belong to you.
There is also a safe migration path, which suggests Meta learned this lesson carefully. Traffic shifts onto ZGateway via configuration flags, not code changes. Percentage knobs ramp traffic. Region filters limit blast radius. A global kill switch rolls back in seconds. They did not flip a boolean and hope.
The Hard Questions: A Practical FAQ
When should you switch from direct access to a proxy?
When your incidents trace back to client behavior you cannot control, and when connection or request fan-out grows faster than your operational bandwidth.
Does the proxy prevent reliability issues or just move them?
It moves them. Connection storms still happen, but they hit the proxy tier instead of the database tier. The difference is that the proxy fleet is built to absorb them, observe them, and harden against them centrally. The database fleet is not.
What fleet size makes this worth it?
Think less about absolute numbers and more about the relationship between your platform team and your client population. If you have fifty clients and one team, you don't have a mesh problem. You have simplicity. Keep it. If you have a thousand clients and a hundred teams, the proxy pays for itself in incident prevention alone.
How much overhead does the hop add?
About six percent computational overhead for an average use case. Latency increases by one network hop. But total persistent connections drop by roughly nineteen times, and hot-key stampedes flatten into single fetches. For most large-scale systems, that trade is obvious. For small systems, it's pure cost.
The Verdict: A Necessary Tax on Scale
The verdict is this. ZGateway is not a performance optimization. It is a scale-induced structural change. Meta added the hop because at their size, the alternative was unbounded failure.
If you are not at that size, admire the engineering, copy the migration discipline, but don't copy the architecture. A proxy is a tax on scale. Pay it only when the bill for direct access comes due.
This is TAKEYOURPILLS DOT TECH. Go ship something.
References
- ZGateway: Learnings from Putting a Proxy in Front of ZippyDB - Engineering at Meta