Uber: organizing 2,200 microservices into domains
At a glance
Section titled “At a glance”| Organization | Uber |
| Period | Described in 2020 |
| Problem | About 2,200 critical microservices with tangled dependencies |
| Architecture | Domain-Oriented Microservice Architecture (DOMA): domains, layers, gateways and extensions |
| Patterns | Microservices, domain-driven design, API gateways |
The problem
Section titled “The problem”Uber’s move to microservices let teams work independently, but with around 2,200 critical services new problems appeared:
- Finding the cause of an incident could mean working through about 50 services owned by 12 teams.
- Call chains ran many layers deep, so a slowdown far away could spread upward.
- A simple feature often needed changes in several teams’ services; one complex integration needed ten.
- Teams changed each other’s services and data models, creating groups of services that had to be deployed together: a distributed monolith.
- Services changed quickly (Uber estimated a service’s half-life at about 18 months), so the services calling them kept having to migrate.
What they did
Section titled “What they did”Uber kept microservices but added structure above them:
- Domains. Related services are grouped into a domain around one area of the business. A domain might hold one service or dozens.
- Layers. Domains sit in five layers: infrastructure, business, product, presentation and edge. A domain may only depend on layers below it, and lower layers are more general.
- Gateways. Each domain has one entry point. Other domains call the gateway, never the services, data or pipelines behind it.
- Extensions. Teams add behaviour to another domain through defined extension points, such as plug-in logic or extra data attached to requests, instead of editing its code.
flowchart TB
edge[Edge layer] --> pres[Presentation layer]
pres --> prod[Product layer]
prod --> gw1[[Gateway: Rides domain]]
prod --> gw2[[Gateway: Maps domain]]
subgraph rides [Rides domain]
gw1 --> r1[Service] & r2[Service]
end
subgraph maps [Maps domain]
gw2 --> m1[Service] & m2[Service]
end
r1 --> infra[Infrastructure layer]
m1 --> infra
Results
Section titled “Results”Uber grouped its 2,200 services into 70 domains, about half of which had been implemented when it wrote about DOMA. It reported:
- 25% to 50% less time for product teams to integrate with a platform, because they call one gateway instead of many services.
- One feature integration falling from three days to three hours using extensions.
- Platform support costs often dropping by an order of magnitude.
- Two large platform rewrites done behind gateways without migrating hundreds of calling services.
Trade-offs
Section titled “Trade-offs”- More structure and governance. Someone has to define domains and layers and keep dependencies pointing the right way.
- Gateways are extra hops and must be designed as stable, versioned APIs.
- It suits large organizations. With a few dozen services, the overhead may outweigh the benefit.
Lessons you can reuse
Section titled “Lessons you can reuse”- Hide groups of services behind one stable interface, so internal changes don’t ripple outward.
- Define allowed dependency directions and enforce them.
- Offer extension points instead of letting other teams edit your services.
Related on ArchitectureCompass
Section titled “Related on ArchitectureCompass”- Microservices
- Shopify’s modular monolith, the same idea inside one codebase
- API-led connectivity
Sources
Section titled “Sources”- Adam Gluck, “Introducing Domain-Oriented Microservice Architecture” (opens in a new tab), Uber Engineering, July 2020
Written and edited by Abhinav Taduka, enterprise software architect.