Uber architecture visualization
Todas as arquiteturas
Análise técnica

Uber

Como a Uber construiu uma plataforma de dados em tempo real pra casar passageiros e motoristas em 10.000 cidades.

Números que importam

30M+
Viagens / dia
10,000+
Cidades
trillions
Mensagens Kafka / dia
100k+
Queries Pinot / seg
P99 < 1s

Stack técnica

Kafka· streaming
Apache Flink· processamento stream
Apache Pinot· OLAP em tempo real
Apache Hudi· formato de tabela
Presto· SQL interativo
Spark· processamento batch
HDFS· armazenamento
Cassandra· store operacional
Michelangelo· plataforma de ML

A arquitetura em um dashboard interativo

A ideia é essa: aprender lendo o diagrama. Cada caixa e cada seta conta uma parte da história — clique pra abrir.

Como ler este diagrama
Caixas = componentes

Cor indica o papel: cliente, streaming, storage, compute, ML, serving. Clique em qualquer caixa pra ver o que é, por que é usada e como funciona ali.

Setas = fluxo de dados
streaming· eventos ao vivobatch· job periódicosync· chamada diretaserve· resposta ao usuário
Clique em uma etapa para explorar
eventosETL batchsurge · sinaisatribuição
App do passage…Clienteclique →
App do motoris…Clienteclique →
KafkaStreamingclique →
FlinkComputaçãoclique →
Apache PinotServiçoclique →
Apache HudiArmazenamentoclique →
Spark ETLComputaçãoclique →
MichelangeloMLclique →
DispatchServiçoclique →
A plataforma da Uber roda dois loops em paralelo: um em tempo real (Kafka → Flink/Pinot → decisões operacionais em segundos) e um batch (Hudi → Spark/Presto → treino de ML que alimenta o dispatch de volta pro app).
Opcional
Ler o deep dive completo em texto
As mesmas ideias do diagrama, com mais contexto — recomendado depois de explorar as etapas.

O problema: 30M de corridas por dia, e cada uma é uma decisão em tempo real

Uber não é um problema de "big data" — é um problema de big real-time. Quando você toca em "solicitar", a plataforma tem que:

  • Achar motoristas próximos (query geo no estado ao vivo dos motoristas)
  • Calcular uma tarifa (modelo de surge baseado nos últimos N minutos de oferta/demanda)
  • Rotear a viagem (ETA a partir do trânsito ao vivo)
  • Pontuar fraude (em <100ms)
  • Atualizar dezenas de sistemas downstream (contabilidade, ganhos do motorista, métricas de marketplace)

Tudo isso em cerca de um segundo. E depois o mesmo evento tem que cair num lakehouse pro re-treino do modelo amanhã. Esse requisito duplo — sub-segundo E analítico — é o que moldou toda escolha da plataforma.

Kafka é o sistema nervoso

Todo evento relevante na Uber flui pelo Kafka. A Uber roda um dos maiores deployments de Kafka do mundo — trilhões de mensagens por dia em milhares de tópicos. Duas decisões de design importam:

  • Tópicos chaveados por entidade, não por serviço. trip_events chaveado por trip_uuid significa que todo consumer vê atualizações ordenadas por viagem.
  • Producers escrevem uma vez; Kafka Connect / uReplicator distribui pra regiões e sinks downstream. Producers não sabem nem se importam pra onde o dado vai.

A Uber também open-sourceou o uReplicator (depois substituído por melhorias do MirrorMaker 2) especificamente pra resolver replicação cross-datacenter na escala deles — o tooling nativo do Kafka não bastava.

Apache Pinot: OLAP sub-segundo em dados ao vivo

Warehouses tradicionais respondem queries analíticas em segundos a minutos. A Uber precisava de milissegundos — pra alimentar dashboards de surge, detecção de fraude, calibração de ETA. Eles co-criaram o Apache Pinot pra preencher essa lacuna.

Pinot é um store OLAP colunar que ingere direto do Kafka e responde queries slice-and-dice em <100ms a 100k+ QPS. Um exemplo concreto:

-- "Quantas viagens completas por cidade nos últimos 5min?"
-- Sustenta o modelo de surge. Roda a cada poucos segundos.
SELECT city_id, COUNT(*) AS trips
FROM trip_events
WHERE event_type = 'TRIP_COMPLETED'
  AND event_time >= ago('PT5M')
GROUP BY city_id;

Mesmo SQL que você escreveria em Postgres. Mas Pinot pré-materializa os segments, mantém dado quente em memória e devolve em 20-50ms. É a diferença entre "surge reagindo à realidade" e "surge reagindo ao que rolou há 20 minutos".

Apache Hudi: o lakehouse antes de lakehouses serem chamados assim

A Uber escreveu o Apache Hudi em 2016, três anos antes de "lakehouse" virar termo de marketing. O problema que resolveram: como fazer upserts em HDFS/S3? Uma viagem pode atualizar dezenas de vezes (aceita → iniciada → completada → ajustada → estornada), e reescrever a partição inteira toda vez era insustentável.

Hudi introduziu dois tipos de tabela que hoje são vocabulário padrão:

  • Copy-on-Write (CoW): reescreve arquivos na atualização. Leitura mais simples, escrita mais cara. Boa pra tabelas com muita análise.
  • Merge-on-Read (MoR): escreve deltas; leitores fazem merge on-the-fly ou via job de compactação. Escrita mais rápida, leitura mais cara. Boa pra tabelas de alta velocidade tipo estado de viagem.

Todo lakehouse moderno (Iceberg, Delta) tem alguma versão disso hoje. Hudi entregou primeiro porque a Uber precisava.

Michelangelo: ML como produto, não como projeto

Michelangelo é a plataforma de ML interna da Uber. O pitch pros times internos: entregue suas features e um ponteiro pros dados de treino, a gente cuida do resto — treino, deploy, monitoring, re-treino. Os mesmos trilhos sustentam detecção de fraude, previsão de ETA, score de motorista, matching.

A ideia arquitetural chave é o feature store como cidadão de primeira classe. Features definidas uma vez (em tabelas Hive/Hudi) e servidas tanto offline (pro treino) quanto online (via um store de baixa latência como Cassandra). Mesmo padrão que a Netflix usa — e toda org séria de ML converge pra isso.

O que você pode de fato roubar desse design

  • OLAP em tempo real é uma camada própria. Se seus dashboards precisam de frescor sub-segundo, não tente fazer o Snowflake resolver. Olhe pra Pinot, Druid ou ClickHouse. Eles existem exatamente pra isso.
  • Upserts no lake não são negociáveis. No momento em que seu dado tem qualquer correção, ajuste ou dimensão que muda devagar, você precisa de um formato de tabela com semântica de upsert. Hudi, Iceberg ou Delta — escolha um, mas escolha.
  • Tópicos Kafka são entidades, não serviços. Um tópico por serviço cria um grafo de pipelines ponto-a-ponto. Um tópico por entidade (user, order, session, trip) cria uma interface estável que todo consumer compartilha.
  • A plataforma de ML É a estratégia de ML. Se todo time constrói seu próprio training loop, você tem cinco plataformas de ML e nenhum aprendizado. Michelangelo (ou algo parecido) é o multiplicador.

Fontes e leituras curadas

As fontes públicas por trás desta análise, com nosso comentário sobre por que valem seu tempo.

Aprenda o que faz isso funcionar

As aulas do DataForge que cobrem as peças dessa arquitetura.

Última atualização:
← Ver todas as arquiteturas