Module 11 · Lesson 3 of 4
API gateways and service discovery
One front door, and finding services that move.
The Gatepass app used to talk to one hostname, api.gatepass.in. Now there are four services, each running between three and forty copies, and the copies come and go every few minutes as autoscaling reacts to traffic. The app should not have to know any of that. Something has to stand at the front door, and something has to keep track of where everyone lives.
One front door
Imagine the app called each service directly: events.gatepass.in, booking.gatepass.in, payments.gatepass.in. Every phone in the wild would then hard-code your internal structure. Merge two services, split one, rename one, and you'd break every app version still installed, some of which won't update for a year.
An API gateway is a single entry point that sits between clients and services. The app keeps calling api.gatepass.in, and the gateway routes by path:
GET /events/...goes to the events servicePOST /bookingsgoes to bookingPOST /payments/webhookgoes to payments
Notifications is dimmed for a reason: it has no public routes. It only listens to events. Not every service needs a door.
What belongs in the gateway
The gateway is the one place every request passes, so it's the natural home for work that's the same for all of them:
- TLS termination. Decrypt HTTPS once, at the edge.
- Authentication. Check the session or token, then pass a trusted
user_idheader inward. Services don't each re-implement login. - Rate limiting. The limits you built in module 8 live here, before a scalper's traffic reaches any service.
- Request IDs. Stamp every request with a unique ID so logs and traces across services can be joined. You'll lean on this in the next lesson.
- Routing and versioning. Send
/v2/bookingsto the new code while/v1keeps working for old apps.
Some teams also let the gateway aggregate: the app's "show page" needs the event, the seat map and the user's existing bookings, so one gateway endpoint calls three services and stitches a single response. That saves the phone three round trips over a slow mobile network. When each kind of client (app, web, partner API) gets its own aggregating layer, it's called a backend for frontend.
What doesn't belong there
The gateway's danger is that it is convenient. Every team can add "just one rule" to it, and in a year it holds pricing logic, seat validation and a discount engine. Now every change needs the gateway team, and you've rebuilt the monolith at the front door.
Keep a simple rule: the gateway knows about requests, not about tickets. Headers, tokens, paths and rates are fine. Anything that needs to know what a seat or a refund is belongs in a service.
Services move: service discovery
Behind the gateway, booking runs twelve copies today. At 10:00, before a big on-sale, autoscaling adds twenty more, each with a fresh IP address. One crashes and is replaced. At 11:00 most of them are removed. How does the gateway, or booking calling payments, know where to send a request right now?
You can't write IPs in a config file. You need service discovery: a live list of healthy instances per service.
It has three parts:
- Registration. When an instance starts and passes its health check, it's added to a registry under its service name. Often the platform does this for you: Kubernetes knows every pod it started.
- Health. The registry keeps checking. An instance that stops answering is removed within seconds, so nobody keeps sending it traffic.
- Lookup. Callers ask "where is booking?" and get the current list.
There are two styles of lookup:
- Server-side discovery. The caller sends to a stable name, like
booking.internal, and a load balancer or DNS behind that name picks a healthy instance. Callers stay simple. This is how a Kubernetes Service works. - Client-side discovery. The caller fetches the instance list from the registry, caches it, and picks one itself. One fewer hop, and the caller can be smarter, for example preferring instances in its own zone. The cost is that every service needs a discovery library in its language.
The service mesh, briefly
Once you have discovery, every service also wants timeouts, retries, mutual TLS between services and per-call metrics. Writing that in every service, in every language, is a lot of repeated code.
A service mesh moves it out of your code. A small proxy (a sidecar) runs next to each instance, and all traffic in and out goes through it. The proxies get the instance lists and rules from a central control plane. Your booking code calls http://payments/charge and the sidecar handles discovery, encryption, retries and metrics.
It's powerful and it isn't free: one more process per instance, an extra hop on every call, and a complex system to operate. Gatepass at four services doesn't need one. At forty services in three languages, it starts to pay for itself.
Check yourself
The booking team wants the gateway to reject bookings for shows that have already started, because 'every booking passes through it anyway'. What should you say?
Key takeaways
- An API gateway gives clients one stable entry point and hides how services are split, so you can reorganise without breaking installed apps.
- Put cross-cutting work there: TLS, authentication, rate limits, request IDs and routing. Keep business rules out.
- The gateway is on every request's path, so run it redundantly and keep it simple.
- Service discovery keeps a live list of healthy instances. Server-side discovery keeps callers simple; client-side saves a hop.
- A service mesh moves discovery, retries and encryption into sidecar proxies. Worth it at many services and languages, not at four.
Finished reading?
Mark it complete to tick it off in the course.