MÓDULO 14 · 3 SEMANAS · SYSTEM DESIGN CAPSTONE

System Design — projetar sistemas que aguentam escala real

Framework de system design, capacity estimation, trade-offs de escalabilidade e disponibilidade, design de sistemas clássicos (URL shortener, Twitter timeline, Uber matching, notificações em escala, search), internals de bancos distribuídos, CDN e cache distribuído, consistência eventual avançada, e como apresentar decisões técnicas sob pressão de entrevista. O módulo capstone que integra os 13 módulos anteriores em problemas de design de sistemas reais.

Duração ~3 semanas
Conceitos 12 fundamentais
Projeto System Design Completo
Pré-requisito Módulos 00–13 · trilha completa
Escalabilidade Disponibilidade Performance

Doze conceitos que fecham a formação com o problema mais comum em entrevistas de engenheiro sênior: design de sistemas reais sob restrições de escala. Cada conceito usa um sistema concreto como veículo — URL shortener, Twitter, Uber, Kafka, Elasticsearch — porque é neles que os trade-offs ficam visíveis. O framework e a vocabulary aprendidos aqui traduzem os 13 módulos anteriores em linguagem de design de sistemas: SLO vira latência P99; circuit breaker vira estratégia de disponibilidade; kafka vira choice arquitetural justificada.

01

Framework de system design — estrutura de uma sessão de design

Os seis passos de uma sessão de system design: clarificar requisitos (funcionais e não-funcionais), estimar escala, definir API, desenhar arquitetura de alto nível, aprofundar componentes críticos, discutir trade-offs e limitações. O que entrevistadores avaliam: clareza de pensamento, articulação de trade-offs, priorização, e comportamento sob ambiguidade. Erros comuns: mergulhar em implementação sem clarificar requisitos; otimizar prematuramente; não justificar escolhas.

estudar →
02

Capacity estimation — números que informam decisões de design

O papel de estimation não é precisão — é ordem de magnitude que direciona arquitetura. Os números de referência que todo engenheiro sênior deve ter internalizados: latências de I/O (RAM vs SSD vs HDD vs rede), throughput de banco de dados (leitura vs escrita), tamanho médio de objetos, capacidade de um único servidor. Derivar: QPS de read e write, storage em 5 anos, banda de rede. Por que estimation muda o design: 1k req/s vs 1M req/s tem soluções radicalmente diferentes.

estudar →
03

URL Shortener em escala global — o "hello world" do system design

Design de um URL shortener (bit.ly, tinyurl) que processa 100M redirects/dia. Requisitos: criar URL curta, redirecionar para original, expiração opcional, analytics básico. Componentes: geração de ID curto (base62, hash, contador sequencial distribuído), storage (SQL vs NoSQL, TTL via Redis), cache para redirects (99% de leituras), CDN edge para latência global, particionamento de analytics. Trade-off central: consistência de analytics vs latência de redirect.

estudar →
04

Twitter timeline — fan-out, celebridades e consistência eventual

O problema de timeline expõe o trade-off entre fan-out on write (pre-computar a timeline de cada usuário quando um tweet é criado) e fan-out on read (montar a timeline no momento da leitura). Leituras são 100x mais frequentes que escritas: fan-out on write favorece leitura mas explode em storage e latência de escrita para usuários com 1M+ seguidores (o "celebrity problem"). A solução híbrida do Twitter real: fan-out on write para usuários comuns, fan-out on read para celebridades, merge na borda.

estudar →
05

Ride-sharing matching — geolocalização, tempo real e consistência

Design do sistema de matching motorista-passageiro (Uber, Lyft). Requisitos críticos: latência de matching <5s, atualização de localização de motoristas em tempo real (cada carro envia GPS a cada 4s), escala global. Componentes: Location Service com geohash para indexação espacial e busca por proximidade, Matching Service com algoritmo de pontuação (distância, rating, tipo de carro), Trip Service para gerenciar estado da corrida, Websocket para notificações em tempo real. O problema de consistência: dois passageiros podem ver o mesmo motorista disponível simultaneamente.

estudar →
06

Messaging system em escala — WhatsApp, Slack e entrega garantida

Design de um sistema de mensagens em tempo real para 500M usuários. O desafio central: garantir entrega exatamente uma vez com ordenação por conversa, escala de storage para histórico, e baixa latência de entrega. Componentes: WebSocket servers com sticky sessions via consistent hashing, message fanout para grupos (fan-out problemático em grupos de 1000+), storage de mensagens particionado por conversation_id, sincronização offline (o receptor estava offline quando a mensagem chegou), e criptografia end-to-end (Signal Protocol).

estudar →
07

Search system — indexação, ranking e latência de busca

Design de um sistema de busca (Google-like para domínio específico, ou Elasticsearch como produto). Pipeline: crawling/ingestão de documentos, tokenização e criação de inverted index, ranking (TF-IDF como base, extensões com ML), serving de queries com latência <100ms. Desafios de escala: índice de 1B documentos não cabe em um servidor (índice shardado), atualização de índice em tempo real vs rebuild periódico, geração de snippets, correção ortográfica. Quando usar Elasticsearch vs construir próprio.

estudar →
08

Notificações em escala — push, email, SMS e entrega confiável

Design de um sistema de notificações que suporta 10M notificações/hora por múltiplos canais (push iOS/Android, email, SMS, in-app). Componentes: Notification Service que recebe eventos e decide canais, templates com personalização, integrações com APNs/FCM/SendGrid/Twilio, filas por canal (isolamento de falhas), retry com backoff exponencial, deduplicação (o mesmo evento não deve gerar duas notificações), e rate limiting por usuário (não inundar). O trade-off entrega garantida vs experiência do usuário.

estudar →
09

Internals de bancos distribuídos — o que está por baixo das escolhas

Por que entender internals importa para system design: a escolha entre Cassandra, DynamoDB, CockroachDB e Postgres não é arbitrária — ela deriva do modelo de consistência necessário, do padrão de acesso, e dos trade-offs de CAP/PACELC. LSM tree (Cassandra, LevelDB) vs B-tree (Postgres) — impacto em write vs read performance. Consistent hashing e virtual nodes. Consensus: Raft vs Paxos em termos práticos. Replicação síncrona vs assíncrona. Leader election. O que "ACID" e "BASE" significam em sistemas reais.

estudar →
10

CDN e cache distribuído — latência global e cache invalidation

CDN como solução de latência geográfica: edge nodes armazenam conteúdo estático próximo ao usuário, reduzindo latência de 200ms para 20ms. Arquitetura multi-camada de cache: browser cache → CDN edge → CDN origin shield → application cache (Redis/Memcached) → banco. Cache invalidation: o problema difícil. Estratégias: TTL (simples mas tem stale data), purge por evento (complexo mas imediato), versioning no URL (sem invalidation, mas requer deploy coordination). CDN para APIs (API acceleration) vs conteúdo estático — diferenças e quando faz sentido.

estudar →
11

Consistência eventual avançada — conflitos, CRDTs e convergência

Consistência eventual é um espectro, não um estado binário. As garantias que os sistemas oferecem: read-your-writes, monotonic reads, causal consistency. CRDTs (Conflict-free Replicated Data Types): estruturas de dados que convergem matematicamente sem coordenação — G-counter, PN-counter, OR-Set. Aplicações: Google Docs (collaborative editing), shopping cart (Amazon Dynamo), feature flags. Versioning com vector clocks para detecção de conflitos. O que não é resolvível sem coordenação — e por que algumas operações exigem serialização.

estudar →
12

Apresentando decisões técnicas — comunicar design sob pressão

A habilidade de system design é dual: pensar bem E comunicar bem. Técnicas para sessões de design: pensar em voz alta (narrar o raciocínio, não só o resultado), verificar com o entrevistador antes de aprofundar ("antes de entrar nos detalhes do banco de dados, faz sentido para você?"), articular trade-offs explicitamente ("escolhi X por A e B, mas abro mão de C"), admitir limitações do design ("se os requisitos fossem Y, precisaria mudar Z"). Como estruturar um ADR (Architecture Decision Record) para comunicar decisões para o time depois.

estudar →
módulo capstone

Este é o módulo que fecha a formação. Não introduz conceitos completamente novos — integra os anteriores em problemas de design reais. SLO (módulo 08) vira latência P99 num capacity estimate. Circuit breaker (módulo 08) vira decisão de disponibilidade num componente de matching. Kafka (módulo 09) vira justificativa de escolha num fan-out de notificações. O engenheiro sênior não responde "como você faria um Twitter" de memória — pensa ao vivo, aplicando os trade-offs que internalizou ao longo dos 13 módulos anteriores.

System design é fundamentalmente sobre decisões com trade-offs — não há resposta certa única. As cinco decisões abaixo aparecem repetidamente em problemas de design diferentes e são as que entrevistadores exploram para avaliar profundidade de entendimento.

SQL vs NoSQL — como escolher para um sistema novo?

A pergunta não é "qual é melhor" — é "quais são os padrões de acesso e os requisitos de consistência?". SQL (Postgres, MySQL) é a escolha padrão quando você precisa de transações ACID, schema bem definido, e queries ad-hoc. NoSQL faz sentido quando o padrão de acesso é por chave primária (DynamoDB), você precisa de schema flexível com evolução rápida (MongoDB), ou precisa de escrita de alta throughput com consistência eventual (Cassandra). O erro mais comum é escolher NoSQL por escala imaginária: Postgres com sharding adequado suporta dezenas de milhões de registros sem problema. Para a maioria dos sistemas, SQL até 10M req/dia; NoSQL quando o padrão de acesso não se encaixa em relacional ou a escala exige sharding automático.

Cache aside vs read-through vs write-through — qual estratégia de cache?

Cache aside (lazy loading): a aplicação verifica o cache, em miss lê do banco e popula o cache. Simples, mas o primeiro acesso sempre é lento e há risco de cache stampede (muitos processos vão ao banco simultaneamente após expiração). Read-through: o cache busca do banco em miss automaticamente — simplifica a aplicação mas requer cache que suporte lógica de busca. Write-through: escreve no cache e no banco simultaneamente — dados sempre atualizados, mas aumenta latência de escrita. Write-behind (write-back): escreve só no cache, persiste no banco de forma assíncrona — throughput de escrita alto, mas risco de perda se o cache cair antes da persistência. A escolha depende da tolerância a stale data e ao risco de perda.

Sincronização síncrona vs assíncrona entre serviços — quando cada uma?

Chamadas síncronas (REST, gRPC) criam acoplamento temporal: se o serviço downstream está lento ou indisponível, o upstream fica bloqueado. Isso cria cascata de falhas. Comunicação assíncrona via filas (RabbitMQ, Kafka) desacopla produtor de consumidor — o produtor não espera o processamento, a fila garante entrega. A decisão não é uma coisa ou outra: é qual operação precisa de resposta imediata para poder continuar. Criar pedido → confirmar pagamento é síncrono (não posso confirmar sem saber se o pagamento foi aprovado). Enviar email de confirmação → é assíncrono (não preciso esperar o email chegar para mostrar "pedido confirmado" ao usuário). A heurística: síncrono para decisões, assíncrono para efeitos colaterais.

Horizontal scaling vs vertical scaling — como pensar a decisão?

Vertical scaling (máquinas maiores) é mais simples: sem mudança de código, sem problema de estado distribuído. O limite é o maior servidor disponível — e custo sobe não-linearmente. Horizontal scaling (mais máquinas) escala sem limite teórico, mas requer que os serviços sejam stateless (ou que o estado seja externalizado para Redis/banco). A estratégia prática: começar vertical até onde fizer sentido economicamente, então horizontalizar. O erro comum em system design é partir para sharding horizontal sem justificar que a escala realmente exige. Para bancos de dados: leitura escala bem com réplicas de leitura (sem sharding); escrita escala só com sharding. Read replicas são a primeira opção, não a última.

Consistência vs disponibilidade — como o teorema CAP se manifesta em decisões reais?

CAP (Brewer, 2000) diz que num sistema distribuído com partição de rede, você escolhe entre consistência (todos os nós veem o mesmo dado) e disponibilidade (o sistema sempre responde). A formulação mais útil para design é PACELC: sem partição, você escolhe entre latência e consistência. DynamoDB e Cassandra escolhem disponibilidade + latência: respondem sempre, possivelmente com dado stale. HBase e Zookeeper escolhem consistência: param de responder em vez de retornar dado errado. Postgres com replicação síncrona escolhe consistência; com assíncrona, escolhe disponibilidade. A pergunta de design é: "o que é pior para o usuário — receber dado de ontem, ou não receber resposta nenhuma?" A resposta determina o ponto no espectro de consistência.

O projeto capstone integra os 13 módulos anteriores num design completo de sistema real. Não é um exercício de memorização de soluções — é um exercício de raciocínio estruturado sob restrições que o engenheiro documenta como se estivesse numa sessão de entrevista real.

PROJETO PRÁTICO

System Design Completo

Escolher um dos três problemas clássicos abaixo e produzir um document de system design completo — não apenas os componentes, mas o raciocínio de cada decisão, as alternativas consideradas e descartadas, e as limitações conhecidas do design proposto. O objetivo é que o documento possa ser apresentado em 45 minutos de sessão de entrevista, com clareza suficiente para que um engenheiro sênior que não participou do processo entenda todas as decisões.

PROBLEMA A — URL Shortener Global
  • 100M URLs criadas/mês, 10B redirects/mês, latência de redirect <50ms globalmente
  • Requisitos funcionais: criar URL curta, redirecionar, expiração, analytics básico (cliques por URL)
  • Design obrigatório: geração de ID (qual algoritmo e por quê), storage (qual banco e particionamento), cache strategy (qual camada e TTL), CDN (como usar para latência global), analytics pipeline (como não impactar latência do redirect)
  • Documentar: o que acontece se o banco de URLs fica indisponível; como garantir unicidade de short URL em ambiente distribuído
PROBLEMA B — Twitter Timeline
  • 500M usuários, 500M tweets/dia, timeline com <200ms de latência, usuários com até 100M seguidores
  • Requisitos funcionais: postar tweet, ver timeline (home feed), ver perfil, follow/unfollow
  • Design obrigatório: estratégia de fan-out (on-write vs on-read vs híbrido), storage de tweets vs storage de timelines, tratamento do celebrity problem, cache de timeline, sincronização entre data centers
  • Documentar: o que muda no design se o requisito de latência for <50ms; trade-off entre freshness da timeline e custo de infraestrutura
PROBLEMA C — Uber Matching
  • 10M motoristas ativos, 50M passageiros, matching em <5s, atualização de localização a cada 4s
  • Requisitos funcionais: solicitar corrida, ver motoristas disponíveis no mapa, aceitar/recusar corrida, rastrear corrida em tempo real
  • Design obrigatório: Location Service (como indexar 10M posições GPS com busca por raio eficiente), Matching Service (algoritmo e critérios), Trip State Machine (estados e transições), comunicação em tempo real (WebSocket vs SSE vs polling), tratamento de motorista que não aceita
  • Documentar: o que acontece se dois passageiros reservam o mesmo motorista simultaneamente; como o sistema degrada gracefully em pico
Escalabilidade Disponibilidade Performance
ENTREGÁVEL POR CAMADA
DIAGRAMA DE ARQUITETURA
Diagrama de componentes com fluxos de dados principais. Não precisa ser ferramenta profissional — pode ser ASCII art ou desenho à mão fotografado. O que precisa estar claro: quais serviços existem, como se comunicam (sync vs async), onde está o estado (qual banco, qual cache), e onde entram CDN, filas e mensageria.
ESTIMATIVAS DE CAPACIDADE
  • QPS de leitura e escrita em hora de pico
  • Storage necessário em 1 ano e 5 anos
  • Banda de rede estimada
  • Número de servidores por componente crítico
  • Custo mensal estimado de infraestrutura (ordem de magnitude)
REGISTRO DE DECISÕES (ADR-STYLE)
Para cada decisão de design importante, documentar no formato: (1) qual era a escolha, (2) quais alternativas foram consideradas, (3) por que esta foi escolhida, (4) quais as limitações conhecidas. Mínimo 5 decisões documentadas desta forma.
ANÁLISE DE TRADE-OFFS
  • Consistência vs disponibilidade — onde o sistema favorece qual lado e por quê
  • Latência vs throughput — onde foram feitos os trade-offs
  • Custo vs performance — o que seria diferente se o orçamento fosse 10x menor ou maior
  • Complexidade vs confiabilidade — o que poderia ser simplificado e qual seria o custo
  • O que o design não resolve e qual seria o próximo passo de evolução
SIMULAÇÃO DE ENTREVISTA
Gravar (áudio ou vídeo) uma sessão de 45 minutos apresentando o design em voz alta, como se fosse para um entrevistador. Incluir: clarificação de requisitos, capacity estimation, walkthrough da arquitetura, deep dive em dois componentes críticos, discussão de trade-offs. Ouvir a gravação e registrar: onde o raciocínio ficou confuso, onde faltou justificar uma escolha, onde demorou demais em detalhe desnecessário.
REVISÃO POR PARES
  • Compartilhar o documento com outro engenheiro (ou usar LLM como revisor) pedindo: "quais decisões não estão justificadas?", "onde você discordaria da escolha?", "o que está faltando?"
  • Iterar com base no feedback — o objetivo é um documento que resiste a escrutínio
  • Comparar com referências de design do mesmo sistema (system design interviews repos, documentos de engenharia publicados por empresas) — onde seu design diverge e por quê
entregável

Documento de system design completo (mínimo 2000 palavras, não há máximo) + diagrama de arquitetura + 5 ADRs de decisões principais + estimativas de capacidade justificadas. Opcional mas altamente recomendado: gravação da sessão de apresentação em voz alta. O documento deve poder ser lido por um engenheiro sênior que nunca viu o problema e em 15 minutos entender todas as decisões e seus trade-offs. Este é o artefato que encerra a formação.

Entrevistas de system design para posições sênior avaliam a capacidade de pensar em voz alta, articular trade-offs, e mostrar julgamento sob ambiguidade — não memorização de soluções. As cinco perguntas abaixo representam os padrões mais frequentes e são as que exploram mais profundidade de entendimento.

Q.01

Design um sistema de feed de atividades (como o feed do Facebook ou LinkedIn). Quais são os principais trade-offs de design, e como eles mudam dependendo da escala de usuários (10k vs 10M vs 1B)?

Q.02

Você precisa design um sistema de rate limiting distribuído que funcione em 50 servidores sem ponto central de coordenação. Como você garantiria que um usuário não consegue mais do que 1000 requests/minuto mesmo que suas requisições cheguem em servidores diferentes?

Q.03

Design o sistema de storage do WhatsApp: 2B usuários, 100B mensagens/dia, mensagens devem ser entregues exatamente uma vez (mesmo que o receptor estivesse offline), e o sistema deve funcionar globalmente com latência baixa. Quais são os três maiores desafios de design e como você abordaria cada um?

Q.04

Um serviço que você design está lento para 1% dos usuários — P99 de 2s enquanto P50 é 50ms. Você não sabe a causa. Descreva a metodologia de diagnóstico que você usaria, as hipóteses que investigaria em ordem, e como usaria as ferramentas de observabilidade disponíveis para chegar à causa raiz.

Q.05

Você tem um banco de dados Postgres com 500M registros que está com I/O de disco saturado em horário de pico. Descreva as opções de otimização em ordem de complexidade crescente — do que você tentaria primeiro (sem mudança de arquitetura) até o que exigiria redesign completo. Quais métricas você coletaria para validar cada intervenção?