System Design Space
Knowledge graphSettings

Updated: June 24, 2026 at 8:21 PM

Introducing Domain-Oriented Microservice Architecture

medium

Uber's 2020 architecture redesign: the move from monolith and distributed monolith toward DOMA, with domain boundaries, layered dependencies, domain gateways, extension points, and governance at Uber scale.

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.

Open source

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

2012-2013

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.
2014-2017

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.
2018+

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

LayerPurposeExamples
Infrastructure layerCore platform primitives every engineering organization needs: storage, networking, observability, and infrastructure identity.Storage APIs, network primitives, infra identity, runtime tooling
Business layerShared business capabilities Uber needs as an organization, not tied to one specific line of business.Payment policies, fraud signals, user profile capabilities
Product layerCapabilities tied to a product line but not to one consumer-facing app instance.Ride request lifecycle, dispatch policies, driver supply logic
Presentation layerFunctionality directly tied to mobile/web user-facing features.App-specific screen flows and UX-specific business behavior
Edge layerSafe 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.

Open chapter

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 sizeDefault fitWhy
StartupMonolith / modular monolithThe point is to test the market cheaply and fast; the operational complexity of a service architecture only gets in the way here.
Mid-size companyClassic microservicesSeveral teams already step on each other in one codebase — you need independent delivery and isolation of technical risk by subsystem.
Large organizationDOMA-style architectureThousands 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

Enable tracking in Settings