Domain-oriented microservice architecture matters because it prioritizes business boundaries over network diagrams and call graphs.
In real design work, the chapter shows how domains, layers, domain-gateway contracts, extension points, and team responsibility only work together when the organization shape does not fight the architecture.
In interviews and engineering discussions, it helps talk about DOMA through organizational coupling, shared-platform team bottlenecks, and coordination cost at large scale.
Practical value of this chapter
Design in practice
Align domain boundaries, dependency layers, and clear team responsibilities.
Decision quality
Align domain-gateway contracts, extension points, and platform APIs.
Interview articulation
Show how architecture and organization design shape delivery speed together.
Failure framing
Control organizational coupling and shared-platform team bottlenecks.
Primary source
Uber Engineering, 2020
Original Adam Gluck article on Uber's architecture redesign and transition to DOMA.
Once you have thousands of services, “more microservices” stops being the answer: the links between them grow faster than teams can track. DOMA (Domain-Oriented Microservice Architecture) is Uber's response to that scale — design not a flat set of independent services but domain-oriented service collections with strict contracts, dependency layers, and explicit extension points, so the system stays manageable.
Conceptually, it carries the ideas of DDD and modular architecture onto the scale of thousands of engineers and services — where the cost of unmanaged coupling is measured in quarters, not hours.
Uber architecture evolution
Monolithic architecture
Uber was operating two large services. While the team grew from dozens to hundreds of engineers the monolith held; past that point availability risk, deployment risk, and the cost of every change started rising fast.
- A failure in a large component hit a large share of the product — availability risk concentrated in one place.
- A single change could touch too much of the product at once, which made releases dangerous.
- Weak separation of concerns across business capabilities.
- Business-logic changes were slow to land.
Transition to microservices
The move improved reliability, team accountability, and development speed at first. But at thousands of engineers the win flipped: the system started to look like a distributed monolith — the network latency of a monolith without its debuggability.
- Cross-service dependencies grew until no one could hold the dependency graph in their head.
- Tracing an incident meant walking through dozens of teams, and investigations dragged on.
- Ownership boundaries and data models blurred, so the “whose service is this” argument came up constantly.
- Cognitive load rose: changing anything meant understanding too much.
DOMA (Domain-Oriented Microservice Architecture)
Uber stopped treating the system as thousands of separate services and reframed it as one large distributed application — one that familiar architectural principles apply to: domain boundaries, layers, contracts, and extensibility.
- The design unit became the domain rather than the single service, so decisions were made at a coarser grain.
- Dependencies became controlled via layered design.
- External interactions moved to gateway contracts.
- Cross-domain integrations used extension points instead of tight direct coupling.
DOMA principles
Design around domains, not individual services
The design unit here is a domain-level service collection that delivers a complete business capability, not a single service. That way ownership lands with one team, and planning changes gets easier: it is clear who to ask.
Domains are grouped into layers
A service in an upper layer may depend only on a lower one, never the other way around. This dependency rule keeps cycles from forming and holds blast radius inside the layer: a change at the bottom does not spread up through the whole system.
Each domain exposes an explicit entry contract
There is exactly one door into a domain from the outside — the domain gateway. It keeps the external contract stable, so the internal implementation can be rewritten without warning consumers.
No direct cross-domain dependencies
No shared code and no shared data model between domains — otherwise domains fuse back into a monolith. Custom integration scenarios go through controlled extension points.
DOMA layers at Uber
| Layer | Purpose | Examples |
|---|---|---|
| Infrastructure layer | Core platform primitives every engineering organization needs: storage, networking, observability, and infrastructure identity. | Storage APIs, network primitives, infra identity, runtime tooling |
| Business layer | Shared business capabilities Uber needs as an organization, not tied to one specific line of business. | Payment policies, fraud signals, user profile capabilities |
| Product layer | Capabilities tied to a product line but not to one consumer-facing app instance. | Ride request lifecycle, dispatch policies, driver supply logic |
| Presentation layer | Functionality directly tied to mobile/web user-facing features. | App-specific screen flows and UX-specific business behavior |
| Edge layer | Safe external exposure and client-aware adaptation of Uber services. | Edge gateways, auth policies, API composition, request shaping |
Core rule: services in upper layers may depend only on lower-layer services.
Contracts
Interservice communication patterns
Gateways and extension points rest on contracts between teams: a blurred contract means a blurred domain boundary.
Domain gateway and extension points
Logic extension via plugins
Services inside a domain expose plugin interfaces. A domain-specific check is added through a plugin, not by forking the core flow — otherwise that flow would have to be maintained in several copies.
Data extension via optional attributes
When a domain needs its own attributes, they are added as optional fields on the core model. That buys extension without direct schema coupling between domains — coupling you cannot untangle later.
Team-owned local extension points
A team may define its own extension points inside its domain — as long as contract and lifecycle stay under its control. Freedom here does not mean losing the boundaries.
This is where the practical point of the domain gateway shows up: as long as the external contract holds, a team moves and rewrites internal services and consumers never notice. The freedom to change the implementation is bought with contract discipline.
Outcomes at scale
- Roughly 70 domains as managed units instead of 2200 services as a flat list — a level you can actually hold in your head.
- Dependencies became predictable: layered design and strict dependency direction stop links from growing in any direction.
- Stable domain gateway contracts decoupled releases: domains migrate and ship independently, without waiting on neighbors.
- A developer has to understand less, and an incident's cause shows up faster — both costs of scale moved down.
When to choose monolith, microservices, and DOMA
| Organization size | Default fit | Why |
|---|---|---|
| Startup | Monolith / modular monolith | The point is to test the market cheaply and fast; the operational complexity of a service architecture only gets in the way here. |
| Mid-size company | Classic microservices | Several teams already step on each other in one codebase — you need independent delivery and isolation of technical risk by subsystem. |
| Large organization | DOMA-style architecture | Thousands of engineers no longer fit a flat grid of services: you need domain boundaries, scalable architecture governance, and systemic coupling someone deliberately keeps in check. |
Common DOMA adoption mistakes
Calling a random group of services a domain without a clear business boundary and ownership model — the label changed, the coupling did not.
A domain gateway as a thin proxy without contract discipline, versioning, and SLA commitments: such a gateway stabilizes nothing and breaks consumers on the first change.
Keeping a shared database or shared schema between domains and calling it DOMA — boundaries exist on the diagram, not in the data.
Drawing layers on paper but violating dependency direction: an upper layer calls peers or upper layers. Then the layers live only in the docs.
References
Related chapters
- Why microservices and integration are needed - Provides system-level context for service boundaries and integration models before applying a domain-oriented structure.
- Decomposition Strategies - How to extract bounded contexts and reduce coupling step by step without losing control along the way — where any move toward domains begins.
- Learning Domain-Driven Design (short summary) - DDD foundations for domain boundaries, team responsibility, and contracts that power the DOMA approach.
- Inter-service communication patterns - Synchronous and asynchronous integration patterns that stabilize domain gateway contracts and cross-domain interactions.
- Service Discovery - Service discovery platform context for scalable runtime communication across domain components.
- Monolith to Microservices (short summary) - A step-by-step migration path from monolith to service architecture with controlled coupling and risk management.
- Uber/Lyft - The company at whose scale domain decomposition and architecture governance stop being theory and become a condition for the system's survival.
