Quando falamos em arquitetura de software, a primeira tentação é buscar respostas definitivas: qual a melhor linguagem? qual banco usar? microservices ou monólito? O problema é que, em system design, não existem verdades absolutas — só trade-offs.
Este é o primeiro artigo da série System Design: da teoria à prática, onde vamos explorar 35 princípios práticos de arquitetura de sistemas em profundidade. A cada capítulo, vamos destrinchar cinco ideias centrais, ilustrar com exemplos reais e conectar com fontes confiáveis do mercado.
Hoje, começamos pelos princípios fundamentais — conceitos universais que estão presentes em qualquer arquitetura, do menor serviço até sistemas distribuídos globais.
1. Todo sistema é um trade-off
Você nunca obtém simultaneamente velocidade, baixo custo e simplicidade.
Sempre vai abrir mão de algo.
Essa ideia ecoa a famosa lei de ferro da arquitetura: não existe almoço grátis. Cada decisão otimiza um eixo, mas compromete outro.
- Se você prioriza performance máxima, aceita custos mais altos e soluções mais complexas.
- Se busca simplicidade, abre mão de flexibilidade.
- Se foca em custo, possivelmente sacrifica latência ou confiabilidade.
📚 Referências:
- Designing Data-Intensive Applications (Martin Kleppmann) — capítulo sobre trade-offs entre consistência, disponibilidade e tolerância a partições.
- The Art of Scalability (Abbot & Fisher) — explora os “trade-offs dimensionais” (custo, tempo e qualidade).
- CAP theorem (Eric Brewer, 2000) — formaliza a impossibilidade de ter consistência, disponibilidade e tolerância a partições ao mesmo tempo.
Exemplo real: O Twitter, ao adotar o Manhattan DB, sacrificou simplicidade para ganhar escala global. O trade-off foi assumido: mais escala, mais custo e complexidade de manutenção.
2. Latência se acumula
A percepção de velocidade do usuário não vem apenas do tempo de resposta de uma requisição, mas da soma de todos os milissegundos perdidos em cada camada. Esse efeito é conhecido como latency compounding.
Uma chamada que adiciona 20ms parece inofensiva. Mas em uma jornada que passa por 15 serviços diferentes, já somamos 300ms. Some a isso rede, autenticação, serialização, logs, e temos 1 segundo extra facilmente.
📚 Referências:
- Designing Distributed Systems (Brendan Burns) — aborda impacto da latência em pipelines distribuídos.
- Google SRE Book — capítulo “The Tail at Scale” sobre como a variabilidade de latência em sistemas distribuídos impacta a experiência.
Exemplo real: A Amazon relatou que cada 100ms adicionais de latência no site representava queda de receita. O Google constatou impacto semelhante na busca.
Insight: performance não é só throughput; é também reduzir o acúmulo invisível de delays.
3. Escalabilidade ≠ Performance
Escalabilidade e performance são conceitos distintos.
- Performance: quão rápido uma requisição é processada.
- Escalabilidade: quão bem o sistema lida quando a carga aumenta.
Um sistema pode responder rápido a uma requisição, mas falhar quando recebe milhares simultâneas. Outro pode escalar horizontalmente para milhões de usuários, mas responder lentamente a cada chamada.
📚 Referências:
- Scalability Rules (Abbot & Fisher) — diferencia escalabilidade de throughput.
- Site Reliability Engineering (Google SRE Book) — discute como disponibilidade e escalabilidade se relacionam, mas não são equivalentes a velocidade.
Exemplo real: O Facebook Messenger separou o motor de chat realtime (focado em latência ultrabaixa) das APIs REST (focadas em escala massiva). Cada subsistema otimiza um eixo diferente.
4. Leituras e Escritas pedem estratégias diferentes
Uma das primeiras lições em bancos distribuídos é: escalar leitura e escalar escrita exigem abordagens diferentes.
- Leituras: podem ser replicadas (read replicas), cacheadas (Redis, CDN) e distribuídas globalmente.
- Escritas: exigem coordenação e consistência — ou mecanismos de compensação.
📚 Referências:
- Designing Data-Intensive Applications — capítulos sobre Replication e Partitioning.
- CQRS (Command Query Responsibility Segregation), formalizado por Greg Young, separa explicitamente os fluxos de leitura e escrita.
Exemplo real: Exchanges financeiras aplicam consistência estrita em operações de escrita (ACID), mas replicam leituras em múltiplos data centers para escala.
5. Projete para mudança, não para perfeição
Um erro clássico é buscar “a arquitetura perfeita”. O que realmente precisamos é de arquiteturas que suportem mudanças contínuas.
O conceito de arquitetura evolutiva (Neal Ford, Rebecca Parsons, ThoughtWorks) enfatiza que os requisitos sempre vão mudar. Em vez de congelar um design perfeito, devemos construir estruturas que aceitem evolução incremental.
📚 Referências:
- Building Evolutionary Architectures (Neal Ford, Rebecca Parsons, Patrick Kua).
- Team Topologies (Matthew Skelton, Manuel Pais) — como as equipes organizam o design de forma adaptativa.
Exemplo real: O Mercado Livre adota fitness functions para validar continuamente decisões arquiteturais. Quando surgem novas demandas, a arquitetura se adapta, em vez de quebrar.
Conclusão — primeiro passo da série
Esses cinco princípios são a base de qualquer system design sólido:
- Todo sistema é um trade-off.
- Latência se acumula.
- Escalabilidade não é performance.
- Leituras e escritas pedem estratégias diferentes.
- Projete para mudança, não para perfeição.
Este artigo abre a série System Design: da teoria à prática, que vai explorar os 35 princípios práticos em blocos temáticos. Nos próximos capítulos:
- Artigo 2 – Bancos de dados e armazenamento: índices, replicação, partições e o dilema eterno da invalidação de cache.
- Artigo 3 – Confiabilidade e consistência: idempotência, eventual consistency e durability.
- E assim seguimos até o capítulo final, onde exploramos o papel de pessoas e processos no sucesso da arquitetura.
Continue acompanhando: no próximo artigo, vamos mostrar onde os gargalos realmente moram — no armazenamento de dados.