// Stay in touch?
Products
Encore CloudEncore Cloud
Encore.tsEncore.ts
Encore.goEncore.go
PricingPricing
Book a DemoBook a Demo
Use Cases
AI-Powered DevelopmentAI-Powered Development
Event-Driven SystemsEvent-Driven Systems
Distributed SystemsDistributed Systems
Case StudiesCase Studies
ShowcaseShowcase
Resources
DocsDocs
InstallInstall
Example AppsExample Apps
Demo videoDemo video
ArticlesArticles
GitHub ReleasesGitHub Releases
Systems Operational
Company
About UsAbout Us
Swag ShopSwag Shop
ContactContact
JobsJobs
PressPress
SecuritySecurity
TermsTerms
Privacy PolicyPrivacy Policy
Data Processing AgreementData Processing Agreement
Enterprise SLAEnterprise SLA
Encore
© 2026 EncoreAll rights reserved
© 2026 Encore All Rights Reserved
GitHubDiscordYouTube

API Gateway Patterns for Microservices

What a gateway does, the patterns worth knowing, and when a small system is better off without one

07/20/26
8 Min Read
Ivan Cernja
07/20/26

API Gateway Patterns for Microservices

What a gateway does, the patterns worth knowing, and when a small system is better off without one

Ivan Cernja
8 Min Read

Stripe's public API sits behind a gateway layer that authenticates every request, enforces per-key rate limits, and routes to the internal services that charge cards or issue refunds. A caller never sees that structure, they see one API at one domain, and Stripe can move a route to a different service without any client noticing. This is the work an API gateway does, giving clients one stable front door while the services behind it stay free to change.

The pattern is useful, and it is also easy to reach for too early. A gateway is another process to run, another hop on every request, and a place where routing and auth logic collects. For a system with a couple of services it often costs more than it returns, so the useful skill is knowing which gateway responsibilities you need and where they should live.

Clients send requests to a single API gateway, which authenticates, rate-limits, and routes each request to one of several backend services.

Web, mobile, partner APIcallers
single entry point
API gateway
backend services
service
Orders
service
Users
service
Catalog
One front door, several services behind it.

What a gateway handles

The word "gateway" covers a bundle of responsibilities that tend to travel together because they all belong at the boundary of the system, before a request reaches any single service. Pulling them apart makes it easier to see which ones you need.

  • Routing. The gateway maps an incoming path or method to a backend service, so /orders reaches the orders service and /users reaches the users service. Clients see one host, and you can move a route to a different service without touching callers.
  • Authentication and authorization. It validates the token or session once at the edge and rejects anonymous traffic before it reaches anything expensive, then forwards a verified identity inward so downstream services do not each reparse credentials.
  • Rate limiting. It caps how many requests a caller can make in a window, which protects the services behind it from a runaway client or an abusive one, and lets you sell tiered API plans.
  • TLS termination. It handles HTTPS at the edge so internal services can talk over plain HTTP inside a trusted network.
  • Request aggregation. It can fan a single client request out to several services and merge the responses, which cuts round trips for a client on a slow connection.

Routing and auth are the two most teams reach for. Aggregation is the one to be careful with, because putting slow, multi-service business logic on the request path is how a thin gateway turns into a fat one that becomes hard to keep available.

Edge auth, and why it belongs at the boundary

Authentication is the responsibility that most clearly benefits from living at the edge. If every service validated tokens on its own, you would duplicate that logic across the codebase and have to update all of it whenever the scheme changed. Doing it once at the boundary keeps token handling in one place, and downstream services receive an identity they can trust rather than a raw credential they have to verify.

The shape is: the gateway checks the credential, resolves it to a caller, and passes that caller inward. A service reads the caller from the request context and makes its own authorization decision, such as whether this user may cancel that order, without going back to the token. Encore models this directly with an auth handler that runs before your endpoints and populates the caller data your handlers read:

import { Header, Gateway } from "encore.dev/api"; import { authHandler } from "encore.dev/auth"; import { getAuthData } from "~encore/auth"; interface AuthParams { authorization: Header<"Authorization">; } interface AuthData { userID: string; } // Runs at the edge, before any endpoint that requires auth. export const auth = authHandler<AuthParams, AuthData>(async (params) => { const userID = await verifyToken(params.authorization); return { userID }; }); export const gateway = new Gateway({ authHandler: auth });

Inside an endpoint marked auth: true, the verified caller is available through getAuthData(), so the endpoint decides what this user is allowed to do without re-checking the token.

When you do not need a dedicated gateway

The strongest argument against a separate gateway is that a small system rarely uses one enough to justify it. With one or two services, routing is trivial, there is no cross-service aggregation to do, and auth can live in a shared middleware. Adding a gateway there gives you an extra deployable, an extra network hop on every request, and a single point of failure to make redundant, in exchange for indirection you do not need yet.

A dedicated gateway starts to pay off when one or more of these is true:

  • You expose several public-facing services and want callers to see one API surface.
  • You have external API consumers who need stable, versioned endpoints and per-key rate limits.
  • You need centralized auth, rate limiting, or request logging applied uniformly across services.
  • Different client types need differently shaped responses, which is the case a Backend for Frontend addresses.

Below that bar, the same responsibilities are better handled by your framework or a shared library than by a standalone component. Many modern backend frameworks fold routing and edge auth into the application itself, which covers the common cases without a separate process to run. The service-to-service communication patterns cover how services then talk to each other behind that boundary.

A decision flow: default to no dedicated gateway; add one only when you have public multi-service APIs, external consumers, or cross-cutting edge needs.

New APIstarting point
the test
Public multi-service API, external consumers, or cross-cutting edge needs?
answer
no
Framework routing and edge auth
yes
Add a dedicated gateway
Reach for a gateway when the system asks for one, not by default.

Keeping a gateway healthy once you have one

A gateway sees every request, so its failure modes matter more than any single service's. Two rules keep it from becoming the weak point. Keep its logic thin, so it routes, authenticates, and rate-limits but does not run slow business logic that ties up a request while it waits on a database. And run it as several instances behind a load balancer with health checks, so no single instance is on the critical path. The Backend for Frontend variant needs extra care here, because a BFF that aggregates several service calls per request is doing real work on the hot path, and you want timeouts and fallbacks so one slow downstream service does not stall the whole response.

ConcernThin gatewayFat gateway
Work per requestRoute, auth, rate-limitAlso aggregates and transforms data
Latency addedSmall, predictableGrows with downstream calls
AvailabilityEasy to keep redundantHarder, more failure paths
Best fitMost systemsBFFs and deliberate aggregation layers

Where Encore fits

A large part of the case for a dedicated gateway is centralizing routing and edge auth across services, and Encore handles both inside the application. You define endpoints as typed functions and mark which require authentication, and Encore generates a gateway that terminates TLS, runs your auth handler at the edge, and routes each request to the right service. There is no separate gateway process to configure and keep running, because the routing and auth live in the same codebase as the services.

Because services call each other with type-checked function calls through the ~encore/clients import rather than over ad hoc HTTP, the internal boundaries a gateway usually hides are already type-safe and traced. For a system that would otherwise stand up a gateway mainly to centralize auth and routing, that need is met by the framework. When you do want a standalone edge component in front of everything, encore build docker produces a standard container image, so putting a dedicated gateway or load balancer ahead of it stays a normal deployment choice. This tends to track the monolith versus microservices decision: the fewer moving pieces you run, the less gateway machinery you need to bolt on.

Related reading

  • Monolith vs Microservices: How to Choose in 2026
  • Service-to-Service Communication
  • How to Build Microservices with TypeScript
  • Message Queues vs Pub/Sub
  • Microservices Best Practices

Frequently asked questions

What does an API gateway do?

An API gateway is a single entry point that sits in front of your services and handles work that would otherwise be repeated in each one. It routes each request to the right service, terminates TLS, authenticates callers, applies rate limits, and can combine responses from several services into one. Clients talk to the gateway instead of to individual services, so internal service boundaries stay hidden and can change without breaking callers.

Do I need an API gateway for microservices?

Not always. A gateway earns its place once you have several public-facing services, external API consumers, or cross-cutting needs like centralized auth and rate limiting. For a small system with one or two services, a dedicated gateway is usually an extra hop and an extra thing to run for little gain. Many backend frameworks already handle routing and auth at the edge, which covers the common cases without a separate component.

What is the difference between an API gateway and a load balancer?

A load balancer spreads traffic across identical copies of a service and works at the connection or HTTP level without understanding your API. An API gateway works at the application level: it reads the request, decides which service should handle it, checks auth, applies rate limits, and can reshape the response. You often run both, with the load balancer in front distributing traffic and the gateway routing by path or method.

What is the Backend for Frontend (BFF) pattern?

Backend for Frontend is a gateway variant where each client type gets its own tailored entry point. A web app, a mobile app, and a partner API each talk to a BFF shaped for their needs, so the mobile BFF can return a smaller payload and merge three service calls into one response. It keeps client-specific shaping out of the core services, at the cost of running and maintaining one gateway per client.

Where should authentication happen in a microservices architecture?

Authenticate at the edge, then pass a verified identity inward. The gateway or API layer validates the token or session once, rejects anonymous traffic early, and forwards the caller's identity to downstream services so each one can make authorization decisions without revalidating the credential. This keeps token handling in one place and means internal services trust a claim they receive rather than parsing raw credentials repeatedly.

Can an API gateway become a single point of failure?

Yes, since every request passes through it, so a gateway needs redundancy, health checks, and enough capacity to absorb traffic spikes. Run it as multiple instances behind a load balancer, keep its logic thin, and avoid putting slow business logic in it. A gateway that only routes, authenticates, and rate-limits is easier to keep highly available than one that also aggregates data from many services on the hot path.

Contents
What a gateway handles
Edge auth, and why it belongs at the boundary
When you do not need a dedicated gateway
Keeping a gateway healthy once you have one
Where Encore fits
Related reading
Encore

The backend platform for humans and agents

Build backends in Go or TypeScript and run them on your own AWS or GCP, with the guardrails your team and AI agents need to ship safely.

Get started

Ready to build your next backend?

Encore is the Open Source framework for building robust type-safe distributed systems with declarative infrastructure.