diogodev_
Conteúdo

System Design: como projetar sistemas escaláveis e resilientes

Construir software vai muito além de escrever código. À medida que uma aplicação cresce, surgem desafios relacionados à escalabilidade, disponibilidade, segurança, desempenho e manutenção. É nesse contexto que entra o System Design, disciplina responsável por projetar arquiteturas capazes de atender aos requisitos atuais e futuros de um sistema.

Independentemente da tecnologia utilizada — Node.js, Java, Go, Python ou qualquer outra — os conceitos de System Design permanecem os mesmos. Entender esses princípios é essencial para desenvolvedores que desejam evoluir para posições de nível sênior, staff ou arquiteto de software.

O que é System Design?

System Design é o processo de definir a arquitetura de um sistema, incluindo seus componentes, fluxos de comunicação, armazenamento de dados e estratégias para garantir desempenho, escalabilidade e confiabilidade.

Enquanto a implementação responde à pergunta "como desenvolver uma funcionalidade?", o System Design busca responder questões como:

  • Como o sistema suportará milhões de usuários?
  • Como evitar pontos únicos de falha?
  • Como garantir alta disponibilidade?
  • Como reduzir a latência das requisições?
  • Como manter os dados consistentes?
  • Como integrar diferentes serviços?

O objetivo é encontrar um equilíbrio entre simplicidade, custo e capacidade de evolução.

Antes de desenhar qualquer arquitetura

Um erro comum é começar desenhando microsserviços, bancos de dados ou filas de mensagens sem entender o problema.

O primeiro passo sempre deve ser compreender os requisitos.

Requisitos funcionais

Descrevem o que o sistema deve fazer.

Exemplos:

  • Cadastro de usuários
  • Login
  • Compra de produtos
  • Upload de arquivos
  • Envio de notificações

Requisitos não funcionais

Definem como o sistema deve se comportar.

Exemplos:

  • Alta disponibilidade
  • Escalabilidade
  • Segurança
  • Baixa latência
  • Tolerância a falhas
  • Observabilidade
  • Recuperação de desastres

Na prática, são esses requisitos que mais influenciam as decisões arquiteturais.

Estimando a carga do sistema

Antes de escolher qualquer tecnologia, é importante estimar o volume esperado.

Perguntas comuns:

  • Quantos usuários existirão?
  • Quantos acessos simultâneos?
  • Qual será o pico de utilização?
  • Quanto armazenamento será necessário?
  • Qual o crescimento esperado?

Imagine uma aplicação com:

  • 10 milhões de usuários
  • Cada usuário realiza 5 requisições por dia

Isso representa cerca de 50 milhões de requisições diárias.

Em horários de pico, o sistema pode receber milhares de requisições por segundo, influenciando diretamente decisões sobre infraestrutura, cache e banco de dados.

Comece simples

Uma boa arquitetura nasce simples.

Cliente



API



Banco de Dados

Não existe motivo para iniciar um projeto pequeno utilizando dezenas de microsserviços, filas e diversos bancos de dados.

A arquitetura deve evoluir conforme surgem novas necessidades.

Evoluindo a arquitetura

Com o crescimento da aplicação, novos componentes podem ser adicionados.

Uma evolução comum seria:

Cliente



CDN



Load Balancer



API



Redis



Banco de Dados

Cada elemento possui uma responsabilidade específica.

CDN

Distribui arquivos estáticos geograficamente, reduzindo latência.

Load Balancer

Distribui requisições entre múltiplas instâncias da aplicação.

Cache (Redis)

Evita consultas repetitivas ao banco de dados.

Banco de Dados

Permanece responsável pela persistência das informações.

Escalabilidade

Existem duas formas principais de escalar um sistema.

Escalabilidade vertical

Consiste em aumentar os recursos do servidor.

Exemplo:

  • Mais CPU
  • Mais memória
  • Mais armazenamento

É simples de implementar, mas possui limites físicos.

Escalabilidade horizontal

Consiste em adicionar novas instâncias da aplicação.

Load Balancer



API 1

API 2

API 3

API 4

Essa abordagem permite crescer praticamente sem limites e é amplamente utilizada em aplicações modernas.

Banco de dados

A escolha do banco depende do problema.

PostgreSQL

Ideal para:

  • Relacionamentos complexos
  • Transações
  • Integridade dos dados

MongoDB

Indicado para:

  • Estruturas flexíveis
  • Documentos JSON
  • Evolução frequente do modelo

Redis

Excelente para:

  • Cache
  • Sessões
  • Rate limiting
  • Filas leves

Elasticsearch

Especializado em:

  • Buscas
  • Indexação
  • Full Text Search

Nenhum banco resolve todos os problemas.

Cache

Grande parte das aplicações realiza mais leituras do que escritas.

Nesse cenário, utilizar cache reduz drasticamente a carga do banco.

Fluxo:

Cliente



API



Redis



Banco

Caso o dado esteja no Redis, a consulta ao banco sequer acontece.

Isso reduz latência e aumenta significativamente a capacidade do sistema.

Balanceamento de carga

Quando existem várias instâncias da aplicação, é necessário distribuir as requisições.

Cliente



Load Balancer



API 1

API 2

API 3

Além da distribuição, o balanceador pode remover automaticamente servidores indisponíveis.

Comunicação assíncrona

Nem todo processamento precisa acontecer imediatamente.

Imagine uma compra online.

Após o pagamento, diversas tarefas podem ser executadas:

  • Enviar e-mail
  • Emitir nota fiscal
  • Atualizar estoque
  • Gerar relatório
  • Notificar outros sistemas

Essas tarefas podem ser processadas por meio de filas.

Compra



Fila



Serviço de Email

Serviço Fiscal

Serviço de Estoque

Serviço de Notificação

Essa estratégia reduz o tempo de resposta para o usuário e melhora a escalabilidade.

Consistência dos dados

Nem todos os sistemas possuem os mesmos requisitos.

Um sistema bancário prioriza consistência.

Uma rede social geralmente prioriza disponibilidade.

Essas decisões estão diretamente relacionadas ao Teorema CAP, que afirma que sistemas distribuídos precisam equilibrar Consistência, Disponibilidade e Tolerância a Partições.

Compreender esse equilíbrio é fundamental para tomar decisões arquiteturais.

Evitando concorrência

Um problema clássico é impedir que dois usuários comprem o mesmo ingresso ou reservem o mesmo quarto de hotel simultaneamente.

Algumas estratégias incluem:

  • Lock pessimista
  • Lock otimista
  • Transações
  • Constraints únicas
  • Idempotência
  • Reservas temporárias
  • Filas de processamento

Cada abordagem possui vantagens e limitações, e a escolha depende das características do sistema.

Segurança

Toda arquitetura deve considerar segurança desde o início.

Algumas práticas fundamentais incluem:

  • HTTPS
  • JWT ou OAuth 2.0 para autenticação
  • Rate Limiting
  • Criptografia de dados sensíveis
  • Validação de entradas
  • Proteção contra SQL Injection
  • Proteção contra XSS
  • Proteção contra CSRF quando aplicável

Segurança não deve ser tratada como uma funcionalidade adicional, mas como um requisito da arquitetura.

Observabilidade

Projetar um sistema também significa facilitar sua operação em produção.

Os três pilares da observabilidade são:

Logs

Registram eventos importantes da aplicação.

Métricas

Permitem acompanhar consumo de CPU, memória, latência, throughput e erros.

Tracing

Acompanha o caminho completo de uma requisição entre diferentes serviços.

Com essas informações é possível identificar gargalos rapidamente.

Alta disponibilidade

Um sistema moderno deve continuar funcionando mesmo diante de falhas.

Algumas estratégias incluem:

  • Replicação de banco de dados
  • Múltiplas instâncias da aplicação
  • Balanceadores de carga
  • Deploy em múltiplas zonas de disponibilidade
  • Backups automáticos
  • Estratégias de Disaster Recovery

Quanto menor o tempo de indisponibilidade, maior a confiabilidade do sistema.

Trade-offs

Uma das principais responsabilidades de quem projeta sistemas é compreender que toda decisão possui vantagens e desvantagens.

Exemplos:

Redis

Vantagens:

  • Alta velocidade
  • Redução da carga do banco

Desvantagens:

  • Cache desatualizado
  • Estratégias de invalidação

Microsserviços

Vantagens:

  • Escalabilidade independente
  • Isolamento de responsabilidades

Desvantagens:

  • Complexidade operacional
  • Comunicação distribuída
  • Observabilidade mais difícil

Kafka

Vantagens:

  • Alto throughput
  • Processamento assíncrono

Desvantagens:

  • Curva de aprendizado
  • Maior complexidade operacional

Um bom arquiteto não escolhe apenas tecnologias populares; ele entende seus custos e benefícios.

Como estudar System Design

Uma forma eficiente de evoluir é praticar sistemas conhecidos.

Alguns exercícios interessantes são:

  • Sistema de venda de ingressos
  • Plataforma de streaming
  • Rede social
  • Aplicativo de chat
  • Marketplace
  • Sistema bancário
  • Encurtador de URLs
  • Sistema de reservas
  • Plataforma de vídeos
  • Serviço de compartilhamento de arquivos

Para cada problema, procure responder:

  • Quais são os requisitos?
  • Onde estão os gargalos?
  • Como escalar?
  • Como garantir disponibilidade?
  • Como evitar concorrência?
  • Como monitorar?
  • Quais são os trade-offs?

Conclusão

System Design não consiste em decorar arquiteturas prontas ou utilizar a maior quantidade possível de tecnologias. O verdadeiro objetivo é compreender o problema, identificar restrições e projetar soluções equilibradas, capazes de evoluir conforme o crescimento da aplicação.

Comece sempre pelo mais simples, valide as necessidades reais do sistema e evolua a arquitetura de forma incremental. Essa abordagem reduz complexidade, facilita a manutenção e evita custos desnecessários.

Dominar System Design é um diferencial importante para desenvolvedores que desejam atuar em projetos de grande escala e assumir responsabilidades relacionadas à arquitetura de software. Mais do que conhecer ferramentas, é a capacidade de tomar decisões técnicas fundamentadas que diferencia um bom desenvolvedor de um excelente arquiteto.

Saiba mais

Livros

  • Designing Data-Intensive Applications (DDIA) — Martin Kleppmann
    Considerado um dos livros mais importantes sobre sistemas distribuídos. Aborda replicação, particionamento, consistência, processamento de dados, mensageria e armazenamento em profundidade.
  • System Design Interview – An Insider's Guide (Volume 1 e 2) — Alex Xu
    Excelente para quem está se preparando para entrevistas, com estudos de caso como Instagram, TinyURL, YouTube, Google Drive e Uber.
  • Software Architecture: The Hard Parts — Neal Ford, Mark Richards, Pramod Sadalage e Zhamak Dehghani
    Focado em decisões arquiteturais, sistemas distribuídos e trade-offs.

Plataformas e cursos

  • ByteByteGo — Conteúdo visual de alta qualidade sobre arquitetura, bancos de dados, cache, filas e sistemas distribuídos.
  • Design Gurus – Grokking the System Design Interview — Um dos cursos mais conhecidos para entrevistas de System Design.
  • Exponent — Mock interviews, exemplos de entrevistas reais e preparação para empresas de grande porte.
  • Educative — Cursos interativos de arquitetura, microsserviços e System Design.

Repositórios no GitHub

  • System Design Primer
    O repositório mais famoso sobre System Design, com conceitos fundamentais, diagramas e dezenas de estudos de caso.
  • Awesome System Design Resources
    Uma coleção com centenas de artigos, vídeos, livros, estudos de caso e conceitos organizados por assunto.
  • Best System Design Resources
    Reúne livros, cursos, cheatsheets, plataformas e questões de entrevistas em um único lugar.