There is a post making the rounds right now from a team that pulled their API gateway out of their architecture on a Thursday afternoon, half expecting to roll it back within the week, and then watched nothing break for three months. Latency improved by the eighteen milliseconds the gateway had been adding. Error rates did not move. Clients never noticed, because from the outside they were hitting the same URLs and getting the same responses, slightly faster. The story ends with a new engineer asking during onboarding why the thing had ever been there, and nobody on the team having a good answer.
I want to take this seriously, because the team did measurement work that almost nobody does. They went back through six months of incident postmortems and counted: fourteen incidents where the gateway was the first suspect checked, two where it was actually the root cause, twelve where ten to fifteen minutes of an active incident were burned ruling it out before anyone found the real problem somewhere else. That is a genuinely useful number and I have never seen another team publish it. They also got the epistemics right at the end, noting that removing infrastructure and having nothing break is not proof it was doing nothing, but it is a strong, testable signal worth investigating rather than dismissing as luck. Good. That is more rigor than most architecture writing carries.
But they diagnosed a cost problem, and the evidence sitting in their own post describes a power problem. The tell is the rate limit configuration. One thousand requests per minute, five hundred for payments, last meaningfully touched twenty-two months ago, and — this is the line that matters — nobody remaining on the team felt confident changing it, because nobody understood the reasoning behind the specific numbers. That is not stale configuration. That is a component with no owner. And once you see it that way, every other finding in the post falls into place. Auth got quietly reimplemented inside each service because no one was accountable for the central implementation being trustworthy. The logging was superseded by distributed tracing and nobody retired the thing it replaced, because retiring it was nobody’s job. The gateway became the default first suspect in every incident precisely because it sat in everyone’s path and belonged to no one. Stripped of ownership, it kept doing the only function that requires no owner at all: moving bytes from one place to another. The gateway has almost never been about the technology — it is about centralizing control, and this one had no control left to centralize. That is why deleting it cost nothing.
So what they actually removed was not an API gateway. It was an internal request router. Read the post again and notice what is missing from the entire story: there is no contract anywhere in it. No OpenAPI, no schema, no spec, no shared definition of what any of those seven services promise. The single most interesting thing they found — that every service team had independently rebuilt the authentication the gateway was supposed to be providing — gets explained in the post as defense in depth, which is a legitimate practice and also, here, the wrong reading. Seven teams did not duplicate that logic because they were being rigorous about layered security. They duplicated it because there was no contract that made the gateway’s behavior legible enough to trust. OpenAPI is the unit of governance, and without one you do not have a gateway enforcing anything. You have a proxy with opinions nobody can read.
What they replaced it with is mostly right, and I want to be fair about that. Pulling authentication into a single shared, versioned library gives you the actual benefit people want from centralized auth — one implementation, one place to fix a bug, one team owning the logic — without a network hop and without two parallel auth paths drifting apart. That is a real improvement. It is also a build-time control replacing a runtime one, and those fail differently. A gateway policy applies to the next request. A library at version 2.4.0 applies to whoever recompiled. One service can sit on 2.1.0 for a year and nothing in the system will tell you, which is the same category of silent erosion they just spent three months discovering. They traded the failure mode, they did not remove it. The rate limiting worries me more concretely: a gateway limit of five hundred per minute on payments was global across the fleet, while a per-service annotation is per instance unless it is backed by shared state. Under autoscaling their real ceiling is now five hundred times however many pods are up, and it moves whenever the autoscaler moves. That is another thing nobody is going to notice for three months.
Then there is the question I would ask first if this were my estate: where does the complete list of your seven services live now? That routing table was almost certainly the only artifact in the building that enumerated the whole surface in one place. Service discovery is not a replacement for it. Consul knows what is currently running and answering; it does not know what exists, what is deprecated, what is contracted to whom, or what got stood up last quarter by a team that has since reorganized. That gap is exactly where API sprawl begins, and sprawl is never really a technical failure — it is an organizational one that shows up in the infrastructure later. At seven services and one team, they are fine. This decision gets expensive somewhere north of twenty.
The other thing I would push on is their list of cases where a gateway genuinely still earns its place: many external partners needing one stable public surface, complex traffic shaping, protocol translation. Those are all real, and they are all 2019 cases. The consumer that changes this calculation is the agent, and the agent is not in their list at all. The moment something needs those seven services federated into a single coherent tool surface, you need aggregation somewhere, and direct service-to-service discovery gives you nothing to aggregate — the consumer decides the gateway, and that consumer has changed since this architecture was drawn. The good news for this team is that their instinct still holds. That layer does not have to be a central box everybody routes through. It can be an MCP server running as a subprocess right next to the agent, on the consumer’s own machine, with the OpenAPI spec as the entire contract and governance living at the most local point possible. But that path requires the specs they do not currently have, which brings us back around to the contract-shaped hole in the middle of the story.
The line I actually want to take from this post is the one they wrote and then under-sold: when every service independently rebuilds what a centralized component was supposed to provide, the centralization has already failed, whether or not anyone has noticed yet. That is true of gateways. It is equally true of the platform team, the center of excellence, the governance council, and every other place where an organization tries to concentrate control it never earned the ownership to hold. There is no platform that saves you. What works is keeping control close to the teams doing the work and coordinating through shared contracts, shared rules, and discovery instead of through a chokepoint. This team got the second half of that right on a Thursday afternoon. Deleting the box was the easy part, and they should feel good about it. Now go write down what those seven services actually promise, because the gateway was never the thing holding this together — and for the last two years, neither was anything else.
