API Gateway

Tool

A layer that puts a single entrance in front of services that each expose their own endpoints, handling shared work like authentication and logging there.

Why it exists

When the server ran as one piece, there was one way in. Requests arrived at a single address, and checking who sent them and writing down what happened took place right there. The code that did the checking lived in exactly one place.

Microservices — splitting one large server into smaller ones that run separately, each owning a feature — turned that one entrance into many. The document service, the notification service, and the billing service each got an address and each took requests directly. Every service then had to repeat the same work: verify that a token is still valid, record who called what, and count whether one caller is asking for too much.

Here is how that played out at Pagedeck. Theo changed the way login tokens are verified and updated six services in turn, but missed one that had been built half a year earlier and barely touched since. That service kept the old scheme, and two months later it turned out to still answer requests carrying tokens from deleted accounts. When the same code exists in six copies, there is no way to confirm that all six copies are currently in the same state.

What it solves

A gateway adds one layer in front of the services. Every request from outside passes through it first, and only what clears it reaches a service behind. Collecting scattered work into one place is the whole idea.

Four jobs end up living there.

  1. Authentication and permission checks. Whether a token is valid and whether this caller may touch this resource gets decided once, at the entrance. Services behind it receive the caller's identity as an already-verified value. When the rule changes, there is one place to change it.
  2. Rate limiting. A cap on how many requests one caller can send in a given window. An integration that accidentally fires thousands of calls per second takes the services behind it down too, so the gateway draws a line — sixty a minute, say — and refuses briefly past it.
  3. Routing. Deciding which service receives a request based on the address it arrived at. From outside there is one address, and splitting or merging services behind it leaves the caller's code untouched.
  4. Logging and observability. Since every request crosses one point, which endpoints are slow and where errors cluster show up on a single screen. Logs that each service wrote in its own format arrive in one format.

Two things come out of this. Shared handling shrinks to one copy, and the address structure the outside world sees stops being tied to the service layout inside. The second one is why splitting a service in two can finish without telling any of the companies integrated with you. A partner who has written /v1/documents into their code keeps calling that address while the team behind it moves the work from one service to three, and the only thing that changes is a routing rule at the entrance.

Alternatives

A gateway isn't always the answer, because the extra layer has a price.

  1. Skip it. With two or three services and no callers except your own web front end, adding a layer costs more than it returns. A gateway is a server too: it gets deployed, watched, and paged for. And since every request crosses it, an outage there is an outage everywhere.
  2. Load balancer. A device that spreads requests across several copies of the same service. Splitting traffic by the front part of an address works here as well. Anything that requires reading the request — unpacking a token, counting calls per user — is out of reach.
  3. A shared library. Bundle the authentication and logging code and pull it into each service. The code is one copy, but if services deploy on different schedules the versions actually running drift apart again. Services written in different languages need one library per language.
  4. A service mesh. A layer that carries traffic between services. Where a gateway guards the path from outside in, a mesh handles the paths from inside to inside. The two aren't substitutes so much as things that sit side by side.

What decides it is less the number of services than who the callers are. If only your own screens call, going without stays comfortable for a long time. Once outside companies start integrating, the entrance needs to be singular. The moment a second team writes your address into their codebase, every rule you want to apply uniformly — who may call, how often, what gets recorded — has to live somewhere that no individual service can skip, and that somewhere is the gateway.

How it sounds at work

"Don't put that check in every service — move it up to the gateway."

A proposal to move shared code into the common layer before it splits into copies.

"If the gateway goes down, everything goes down. Let's run it redundantly first."

Deal with the risk created by funneling everything through one point.

"Take external integrations through the gateway only and let internal calls go direct."

Route traffic from outside and traffic from inside down different paths.

Pagedeck adopted a gateway because of the token incident, not because a feature demanded it. Theo moved authentication up first and left everything else alone, since moving one thing at a time keeps it obvious where to look when something breaks. Rate limiting went up two weeks later, and aligning log formats got pushed to the following quarter.

Some things deliberately stayed put. The rule deciding who may view a given document stayed in the document service. That decision needs the document's sharing settings and the viewer's team, and an entrance that starts learning things like that grows into a second server.

What people get wrong

The most common assumption is that services behind a gateway no longer have to think about security. Every request crosses the entrance, so the inside looks like a cleared zone. But services calling each other don't cross it, and neither does an internal address opened temporarily during an incident or a misconfigured firewall rule. If a service doesn't verify the request in front of it on its own, anyone who gets a foot inside can open every door after that.

Piling processing logic onto the gateway is the other familiar path. Everything passes through, so handling anything there looks fast and convenient. Then code that merges responses, computes values, and handles special cases accumulates, and the structure built to be split ends up with a block in front of it that nobody dares touch. The entrance should judge requests and pass them along; what gets computed and how belongs to the services behind it, or splitting them bought nothing.

Where to go next

  • API

    see what this layer sits in front of

  • API versioning

    the other operations-side tool, for when the contract itself changes

Last updated 2026-09-16