PATTERN Cited by 1 source
Layered gateway architecture¶
Problem¶
An API gateway serving mobile/web clients across many lines of business drifts into a catch-all layer over time:
- Pure routing (what it should be) gets mixed with business logic (what it shouldn't be).
- View-generation (response shaping for clients) mixes with orchestration (calling many downstream services).
- Per-product-line code accumulates in one repo, creating cross-product coupling.
- Language/framework choice ossifies (Node.js + JavaScript in the 2011–19 Uber case) even after the rest of the org moves on.
The result: a gateway that's itself a distributed-monolith bottleneck. Uber's RTAPI hit this state by 2019.
Solution¶
Split the gateway into four explicit layers, each with a narrow contract:
| Layer | Role | Forbidden |
|---|---|---|
| Edge Layer | API lifecycle management (auth, rate-limit, routing) | Business logic |
| Presentation Layer | Microservices for view-generation + data aggregation over downstream services | Business-logic ownership |
| Product Layer | Reusable functional APIs describing a product | Client-shaping logic |
| Domain Layer | Leaf-node microservices providing a single capability | Cross-product orchestration |
- Edge stays clean — only API-lifecycle concerns.
- Presentation owns the view shape for each client (mobile, web, partner) and aggregates from Product + Domain.
- Product owns reusable functional APIs that other teams can compose.
- Domain owns single capabilities — the atomic building blocks.
Canonical instance — Uber Edge Gateway (2020)¶
"So we built a new Edge Gateway to start standardizing on the following layers: Edge Layer: API lifecycle management layer. No extraneous logic can be added keeping it clean. Presentation Layer: microservices that build view generation and aggregation of data from many downstream services. Product Layer: microservices that provide functional and reusable APIs that describe their product. Can be reused by other teams to compose and build new product experiences. Domain Layer: microservices that are the leaf node that provides a single refined functionality for a product team."
— sources/2024-03-14-highscalability-brief-history-of-scaling-uber
Replaced RTAPI across Uber's many lines of business (Uber Eats, Freight, ATG, Elevate), restructuring the 1000s-of-engineers' work without slowing product velocity.
Primary-source references: - Uber Edge Gateway launch - API gateway evolution at Uber
Why this works¶
- Each layer has a narrow contract. Changes in Domain don't propagate through the whole stack; changes in Edge routing don't require Product code changes.
- Independent team ownership. Each layer can be owned by a different team (platform team for Edge; product teams for Product + Domain; a shared team for Presentation).
- Reuse compounds at the right layer. Product-layer APIs are designed for reuse; Presentation-layer shaping isn't.
- Language/framework upgrades happen per-layer. Uber could rebuild Edge without touching Domain services.
When to use¶
- Multiple consumer types (mobile + web + partner API) over a large service mesh.
- Large engineering org (100s to 1000s of engineers) where team boundaries matter.
- An existing gateway has accumulated ad-hoc business logic and is showing strain.
When not to use¶
- Small product with a single consumer type and one team — a BFF or simple API gateway is cheaper.
- Fewer than ~10 downstream services — the layering overhead exceeds the payoff.
Related¶
- systems/uber-edge-gateway — the canonical deployment of this pattern.
- systems/uber-rtapi-gateway — the predecessor that motivated the layering.
- concepts/backend-for-frontend — the BFF pattern is a special case of a single-layer Presentation.
- concepts/separation-of-concerns — the underlying design principle.
- companies/uber — origin org.