Uber DOMA: Como Camadas de Domínio Domaram a Explosão de Microsserviços
Ouvir estudo
gerado ao ouvirGerado apenas no primeiro play
Com tecnologia Amazon Polly + OmniVoice
Com mais de 2.200 microsserviços e dependências cruzadas incontroláveis, a Uber enfrentava um problema clássico de escala organizacional disfarçado de problema técnico. A resposta foi DOMA — Domain-Oriented Microservice Architecture — uma abordagem que agrupa serviços em domínios, expõe interfaces bem definidas e introduz camadas de abstração para recuperar a coesão perdida. Este teardown reconstrói a arquitetura, analisa as decisões e aponta o que eu faria diferente.
Microsserviços prometem autonomia e velocidade. Na prática, sem disciplina estrutural, entregam um grafo de dependências caótico que nenhum engenheiro consegue raciocinar completamente. A Uber chegou a 2.200+ serviços e precisou inventar uma nova camada de organização — não para os computadores, mas para os times.
Ficha Técnica
- Empresa
- Uber Technologies
- Domínio
- Mobilidade urbana, entregas, logística
- Escala de serviços (pré-DOMA)
- ~2.200 microsserviços ativos
- Publicação do artigo DOMA
- Setembro de 2020
- Stack principal
- Go, Java, Python; gRPC; Kafka; Cadence (orquestração de workflows)
- Rede de entrega
- Multi-região, presença global, data centers próprios + nuvem híbrida
- Problema central
- Acoplamento cruzado incontrolável entre serviços sem fronteiras de domínio claras
- Solução adotada
- DOMA — Domain-Oriented Microservice Architecture com camadas, gateways e extensões
O Problema: Quando Microsserviços Viram um Monólito Distribuído
A Uber cresceu de um monólito Python para uma arquitetura de microsserviços ao longo de vários anos, impulsionada pela necessidade de escalar times independentes em múltiplos produtos — Rides, Eats, Freight, ATG. O resultado natural desse crescimento foi uma explosão de serviços: cada time criava o que precisava, quando precisava, sem uma visão global das dependências.
O sintoma mais visível era o que o time de engenharia chamou internamente de dependency hell: um serviço de pagamento chamando diretamente um serviço de mapeamento de rotas; um serviço de notificações acoplado a lógica de precificação; ciclos de dependência que tornavam deployments simples em eventos de coordenação complexos. Com 2.200+ serviços, nenhum engenheiro individual conseguia ter um mapa mental confiável do sistema.
O problema não era técnico na raiz — era organizacional. Conway's Law operando em escala máxima: a arquitetura do sistema espelhava a estrutura de comunicação dos times, que por sua vez era caótica porque cresceu organicamente sem uma taxonomia de responsabilidades. A solução precisava atacar os dois lados: estrutura técnica e estrutura organizacional simultaneamente.
Além do acoplamento, havia um problema de descoberta e reuso. Times criavam serviços duplicados porque não sabiam que a funcionalidade já existia em outro lugar. A ausência de um contrato explícito entre serviços significava que qualquer mudança interna podia — e frequentemente causava — quebras em cascata em consumidores que nunca deveriam ter acesso direto àquela implementação.
Arquitetura DOMA Reconstruída
Visão em camadas da organização de domínios na Uber. Cada domínio expõe uma Layer Interface (gateway) e pode conter sub-domínios. Serviços internos são opacos para consumidores externos ao domínio. Extensões permitem customização sem modificar o núcleo.
- Mobile App · iOS / Android
- Partner API · External Consumers
- API Gateway · Auth / Rate Limit / Routing
- Rides Layer Interface · (Domain Gateway)
- Dispatch Service · (internal)
- Driver Matching · (internal)
- Rides Extension · (customization hook)
- Payments Layer Interface · (Domain Gateway)
- Billing Service · (internal)
- Fraud Detection · (internal)
- Maps Layer Interface · (Domain Gateway)
- Routing Engine · (internal)
- ETA Prediction · (internal)
- Observability Platform · Metrics / Tracing / Logs
- Kafka · Event Bus
- Cadence · Workflow Orchestration
- Rides DB · (Schemaless / MySQL)
- Payments DB · (isolated)
- Maps Cache · (Redis / in-memory)
Como o DOMA Funciona: Domínios, Camadas e Contratos
O DOMA introduz quatro conceitos centrais que, em conjunto, reconstroem a ordem em um ecossistema de microsserviços caótico.
1. Domínios (Domains): Um domínio é uma coleção de microsserviços que representam uma área de negócio coesa — Rides, Payments, Maps, Driver, etc. A granularidade não é arbitrária: segue as linhas de responsabilidade dos times (Conway's Law deliberadamente aplicada, não acidental). Cada domínio tem um owner claro, um roadmap independente e uma fronteira de responsabilidade explícita.
2. Camadas (Layers): Domínios são organizados em camadas hierárquicas. Camadas inferiores (plataforma, infraestrutura) não podem depender de camadas superiores (produto, experiência). Essa restrição unidirecional é a chave para eliminar ciclos de dependência. Na prática, a Uber definiu camadas como: Infrastructure → Platform → Business Domain → Product → Experience. Um serviço de Maps não pode depender de lógica de Rides; um serviço de Rides pode depender de Maps.
3. Layer Interface (Gateway de Domínio): Cada domínio expõe exatamente uma interface pública — o Layer Interface. Serviços internos ao domínio são completamente opacos para o mundo externo. Consumidores externos só podem interagir com o domínio através dessa interface, que funciona como um API Gateway interno. Isso cria um contrato estável: o domínio pode refatorar sua implementação interna livremente, desde que mantenha a interface.
4. Extensões (Extensions): Extensões são o mecanismo de customização sem modificação. Em vez de um consumidor fazer fork de um serviço ou adicionar lógica condicional no núcleo ("se produto X, então..."), ele registra uma extensão que é invocada em pontos específicos do fluxo do domínio. É essencialmente o padrão Strategy/Plugin aplicado em escala de plataforma. Isso foi crítico para a Uber porque produtos diferentes (Rides vs. Eats vs. Freight) precisam de comportamentos ligeiramente diferentes nos mesmos domínios base.
A combinação desses quatro elementos cria o que o artigo da Uber chama de "structured modularity" — modularidade com regras de composição explícitas, não apenas decomposição arbitrária. O resultado prático é que o grafo de dependências, antes um espaguete, passa a ter uma topologia de DAG (Directed Acyclic Graph) com camadas bem definidas.
A Dimensão Organizacional: Por Que Isso É Tanto um Problema de Times Quanto de Código
Um aspecto que o artigo da Uber trata com seriedade e que muitas análises superficiais ignoram: DOMA não é apenas uma reorganização de código. É uma reorganização de responsabilidades e poder de decisão.
Antes do DOMA, qualquer time podia criar dependências em qualquer serviço. Isso parece democrático, mas na prática significava que ninguém era responsável por nada de forma abrangente. O time de Payments não podia refatorar seu serviço de billing sem coordenar com 40 consumidores diretos que tinham acoplamento com detalhes de implementação interna.
Com DOMA, o Layer Interface cria uma fronteira de propriedade clara. O time dono do domínio é o único árbitro de quais funcionalidades são expostas publicamente. Isso tem consequências políticas reais: times de produto que antes podiam "pular a fila" acessando serviços internos diretamente agora precisam negociar adições à interface pública com o time dono. Isso é atrito intencional — o tipo de atrito que força conversas sobre design em vez de gambiarra.
O mecanismo de extensões é particularmente inteligente do ponto de vista organizacional. Ele resolve o problema clássico de plataformas: como um serviço central atende às necessidades divergentes de múltiplos produtos sem se tornar um gargalo ou um acumulador de lógica condicional? A resposta do DOMA é inverter o controle — o domínio define os pontos de extensão, os produtos registram seus comportamentos específicos. O time de plataforma não precisa conhecer todos os casos de uso; os times de produto não precisam de acesso ao núcleo.
Isso também tem implicações para hiring e onboarding. Um engenheiro novo no time de Payments precisa entender apenas o domínio de Payments e suas interfaces com domínios adjacentes — não o sistema inteiro. A complexidade cognitiva é delimitada pela fronteira do domínio. Em um sistema com 2.200 serviços sem essa estrutura, o onboarding efetivo levava meses; com DOMA, o escopo de aprendizado inicial é drasticamente reduzido.
Matriz de Decisões: Alternativas Consideradas
DOMA (abordagem adotada)
- Preserva autonomia dos times dentro do domínio
- Contratos explícitos via Layer Interface reduzem acoplamento acidental
- Extensões permitem customização sem modificar núcleo
- Compatível com migração incremental — não exige big bang
- Overhead de governança: quem decide as fronteiras dos domínios?
- Layer Interface pode virar gargalo de latência se mal implementado
- Extensões mal gerenciadas recriam o problema de acoplamento em outro nível
Melhor equilíbrio para a escala e maturidade organizacional da Uber
Consolidação em Monólito Modular
- Elimina latência de rede entre serviços do mesmo domínio
- Transações ACID dentro do módulo sem coordenação distribuída
- Inviável para a escala de times da Uber — conflitos de merge, deploys acoplados
- Perde os benefícios de isolamento de falha já conquistados
- Migração de 2.200 serviços para monólito é risco inaceitável
Rejeitado — retrogredir não resolve o problema organizacional
Service Mesh Puro (Istio/Envoy) sem reorganização de domínios
- Melhora observabilidade e controle de tráfego sem mudança de código
- Aplica políticas de segurança (mTLS) de forma transparente
- Não resolve o problema de acoplamento lógico — apenas adiciona visibilidade a ele
- Não endereça a questão de ownership e responsabilidade de times
Complementar, não substituto — necessário mas insuficiente sozinho
API Management Centralizado (estilo ESB)
- Controle centralizado de contratos e versioning
- Recria o gargalo do ESB — ponto único de falha e bottleneck de deploy
- Vai contra a filosofia de autonomia de times que a Uber já havia conquistado
- Não escala com 2.200 serviços sem fragmentação do próprio ESB
Rejeitado — antipadrão conhecido para essa escala
Leitura pelos Pilares Well-Architected
Segurança
Positivo: A Layer Interface como único ponto de entrada do domínio cria um perímetro natural para aplicar autenticação, autorização e auditoria. Serviços internos ficam inacessíveis diretamente, reduzindo a superfície de ataque. Gap identificado: O artigo não detalha o modelo de autorização entre domínios — em sistemas financeiros, precisaria de controle explícito de quais domínios podem chamar quais interfaces, com auditoria de cada chamada cross-domain. A Uber provavelmente resolve isso via seu service mesh (Envoy + mTLS + RBAC), mas a integração com DOMA não é documentada publicamen
Confiabilidade
Positivo: O isolamento por domínio limita o blast radius de falhas. Uma degradação no domínio de Maps não propaga diretamente para Payments. As extensões, se implementadas com circuit breakers, permitem que o fluxo principal continue mesmo quando uma customização falha. Gap: O Layer Interface introduz um hop adicional em cada chamada cross-domain. Se não for implementado com caching adequado e circuit breakers, pode virar um ponto de falha concentrado. A Uber usa Cadence para workflows de longa duração, o que mitiga falhas transientes, mas a resiliência do próprio gateway de domínio pr
Eficiência de performance
Trade-off explícito: DOMA adiciona latência em chamadas cross-domain ao forçar o roteamento pelo Layer Interface em vez de chamadas diretas ponto-a-ponto. Para a Uber, onde latência de matching de motoristas é crítica (centenas de milissegundos fazem diferença na experiência), isso é um custo real. O artigo não quantifica esse overhead. Minha estimativa conservadora é 1-5ms por hop adicional em uma infraestrutura bem otimizada — aceitável para a maioria dos fluxos, mas potencialmente significativo em caminhos críticos com múltiplos saltos de domínio.
Otimização de custos
Positivo: Melhor reuso de serviços reduz duplicação — times param de recriar funcionalidades que já existem em outros domínios. Negativo: O Layer Interface de cada domínio precisa ser um serviço de alta disponibilidade, o que significa redundância, monitoramento e manutenção adicionais. Com dezenas de domínios, isso é um custo operacional não trivial. A Uber tem escala para absorver isso; empresas menores precisariam avaliar se o overhead de infraestrutura compensa os ganhos de organização.
Sustentabilidade
O reuso de serviços via Layer Interface reduz a proliferação de instâncias redundantes, o que tem impacto positivo em consumo de recursos computacionais. Menos duplicação de código significa menos superfície de manutenção e menor probabilidade de manter serviços zumbi ativos desnecessariamente. Não há dados públicos sobre o impacto de DOMA em eficiência de recursos na Uber.
DOMA é uma das contribuições mais honestas e práticas que já vi publicadas sobre arquitetura de microsserviços em escala. Não é teoria — é uma solução que emergiu de dor real. Mas há três pontos onde eu divergiria ou complementaria. 1. Contratos como artefatos de primeira classe, não como convenção. O Layer Interface é uma ideia poderosa, mas o artigo da Uber não detalha como os contratos são versionados, testados e evoluídos. Em sistemas financeiros onde trabalhei, a ausência de contract testing explícito (Pact, Protolock para gRPC) significa que "a interface não mudou" é uma promessa baseada em disciplina humana, não em enforcement automatizado. Eu adicionaria contract testing como gate obrigatório no CI/CD de qualquer mudança em um Layer Interface. 2. O modelo de extensões precisa de um registro centralizado com visibilidade. Extensões resolvem o problema de customização, mas criam um novo problema de descoberta: quais extensões estão registradas em qual domínio? Quem as possui? Em um sistema com dezenas de domínios e centenas de extensões, isso vira um grafo de dependências de segundo nível. Eu implementaria um registry de extensões com ownership explícito, SLOs e alertas de extensões órfãs. 3. A dimensão de segurança precisa ser cidadã de primeira classe no modelo. DOMA define fronteiras organizacionais e técnicas, mas não define fronteiras de segurança explicitamente.
Lições Transferíveis: O Que Qualquer Organização Pode Aprender
DOMA é frequentemente descartado como "coisa de Uber" — uma solução para uma escala que a maioria das empresas nunca atingirá. Essa leitura é equivocada. Os princípios são aplicáveis muito antes de você ter 2.200 serviços.
A explosão de microsserviços começa cedo. Na minha experiência, times de 30-50 engenheiros já sofrem com os sintomas que o DOMA resolve: dependências cruzadas não documentadas, duplicação de funcionalidades, onboarding lento. Você não precisa esperar 2.000 serviços para introduzir fronteiras de domínio.
Comece com o mapa de dependências, não com a reorganização. Antes de qualquer mudança estrutural, torne visível o que existe. Ferramentas como Backstage (CNCF) ou até um grafo simples gerado a partir dos logs do service mesh revelam os padrões de acoplamento. O mapa é o diagnóstico; DOMA é um tratamento possível.
O Layer Interface é aplicável mesmo sem microsserviços. Em monólitos modulares, o mesmo princípio se aplica: módulos expõem interfaces públicas explícitas, implementações internas são privadas. A diferença é que a fronteira é de pacote/módulo em vez de rede. O padrão é agnóstico ao estilo de deployment.
Extensões são o padrão correto para plataformas internas. Qualquer time que constrói uma plataforma interna enfrenta o dilema: ser genérico demais (inútil) ou específico demais (não reutilizável). O modelo de extensões do DOMA — define os pontos de variação, deixa os consumidores injetarem o comportamento — é a resposta correta para esse dilema e se aplica independentemente da escala.
Veredicto
DOMA é uma das contribuições arquiteturais mais substanciais publicadas por uma empresa de tecnologia na última década — não porque seja revolucionária em teoria, mas porque é uma solução honesta e documentada para um problema que a maioria das organizações enfrenta e poucos resolvem de forma sistemática. A combinação de domínios, camadas, Layer Interface e extensões não é apenas uma reorganização técnica: é um framework de governança que alinha estrutura de código, estrutura de times e estrutura de responsabilidades. Os pontos fracos são reais: overhead de latência nos gateways de domínio, risco de que extensões mal gerenciadas recriem o problema original em outro nível, e ausência de um modelo de segurança explícito integrado ao framework. Mas esses são problemas de implementação, não falhas de design. O que mais me impressiona no DOMA é o reconhecimento explícito de que arquitetura de software é inseparável de design organizacional. Não há solução técnica para um problema de Conway's Law que não passe também por uma mudança na estrutura de ownership e comunicação dos times. A Uber entendeu isso e construiu uma solução que ataca os dois lados.
Post-mortems, ADRs e deep dives de arquitetura no seu email — do jeito que um arquiteto lê.
Sem spam · cancele quando quiser
Pergunte ao Fernando sobre isto
Receba uma resposta focada sobre este estudo do meu assistente de IA, baseada no meu trabalho.
Participe da conversa
Entre para comentar
Confirme seu e-mail para participar — você também recebe a newsletter. Sem senha.