Nos últimos meses, comecei a estudar um assunto que aparece cada vez mais na rotina de desenvolvedores: System Design.
Apesar de já trabalhar há alguns anos com desenvolvimento de software, percebi que existe uma diferença importante entre saber implementar funcionalidades e saber projetar um sistema como um todo.
Foi justamente essa diferença que me motivou a estudar o assunto.
O que é System Design?
De forma simples, System Design é o processo de definir como diferentes componentes de um sistema vão se organizar e se comunicar para atender determinados requisitos.
Quando desenvolvemos uma aplicação pequena, podemos pensar principalmente em coisas como:
- Qual endpoint preciso criar?
- Qual tabela preciso adicionar?
- Qual componente preciso implementar?
Conforme o sistema cresce, outras perguntas começam a aparecer:
- Quantas requisições o sistema precisa suportar?
- Como os dados serão armazenados?
- Como evitar que um único componente se torne um gargalo?
- O que acontece quando um serviço fica indisponível?
- Como escalar a aplicação?
- Onde utilizar cache?
- Quando utilizar filas?
- Como monitorar o sistema?
- Como garantir consistência dos dados?
- Como lidar com picos de tráfego?
System Design está muito mais relacionado a essas decisões.
Um exemplo simples
Imagine uma aplicação de e-commerce.
Em uma primeira versão, poderíamos ter algo relativamente simples:
Cliente
↓
API
↓
Banco de Dados
Para uma aplicação pequena, isso pode ser suficiente.
Mas imagine que a aplicação cresça e passe a receber milhares de requisições simultâneas.
Agora podemos começar a introduzir novos componentes:
┌──→ Cache
│
Cliente → Load Balancer → API → Banco de Dados
│
└──→ Message Queue → Workers
Cada componente resolve um problema específico.
O Load Balancer pode distribuir as requisições entre diferentes instâncias da aplicação.
O Cache pode evitar consultas repetitivas ao banco de dados.
Uma Message Queue pode permitir que determinadas operações sejam processadas de forma assíncrona.
Os Workers podem consumir essas mensagens e executar tarefas em segundo plano.
O banco de dados continua sendo importante, mas agora não precisa necessariamente ser responsável por todo o trabalho.
System Design não significa simplesmente adicionar tecnologias
Uma coisa que comecei a perceber estudando o assunto é que projetar sistemas não significa simplesmente adicionar Redis, Kafka, Kubernetes ou microsserviços porque são tecnologias populares.
Cada componente adiciona complexidade.
Se uma aplicação recebe poucas requisições e possui um domínio relativamente simples, introduzir dezenas de serviços pode criar mais problemas do que resolver.
Por isso, uma parte importante de System Design é entender trade-offs.
Por exemplo:
Devemos utilizar cache?
A resposta não é simplesmente “sim”.
Precisamos considerar:
- O dado é consultado frequentemente?
- Ele muda com muita frequência?
- Podemos aceitar dados temporariamente desatualizados?
- Qual será a estratégia de invalidação?
- O custo de manter o cache compensa?
A mesma lógica vale para bancos SQL vs. NoSQL, monólito vs. microsserviços, processamento síncrono vs. assíncrono e diversas outras decisões.
Requisitos funcionais e não funcionais
Outro conceito importante é separar os requisitos do sistema.
Os requisitos funcionais descrevem o que o sistema precisa fazer.
Por exemplo:
- Usuários podem criar uma conta.
- Usuários podem realizar pedidos.
- Administradores podem cancelar pedidos.
Já os requisitos não funcionais descrevem características relacionadas ao funcionamento do sistema.
Por exemplo:
- Suportar 10.000 requisições por segundo.
- Ter disponibilidade de 99,9%.
- Responder às requisições em menos de 200 ms.
- Permitir crescimento horizontal.
Essa distinção é importante porque os requisitos não funcionais influenciam diretamente as decisões de arquitetura.
Escalabilidade
Um dos conceitos mais associados a System Design é escalabilidade.
Existem duas formas comuns de pensar sobre isso.
Escalabilidade vertical significa aumentar os recursos de uma máquina:
4 CPU / 8 GB RAM
↓
16 CPU / 32 GB RAM
Já a escalabilidade horizontal significa adicionar mais máquinas ou instâncias:
┌→ API 1
Load Balancer├→ API 2
└→ API 3
A escalabilidade horizontal costuma ser especialmente importante quando precisamos distribuir carga e evitar depender de uma única instância.
Mas novamente: isso não significa que horizontal seja sempre melhor. A decisão depende dos requisitos e das características do sistema.
O que estou estudando
Estou começando a organizar meus estudos de System Design em alguns conceitos fundamentais:
Arquitetura: monólitos, microsserviços e componentes distribuídos.
Bancos de dados: SQL, NoSQL, índices, replicação, particionamento e consistência.
Performance: caching, CDN, load balancing e otimização de consultas.
Comunicação: APIs, filas, eventos e processamento assíncrono.
Confiabilidade: redundância, tolerância a falhas, disponibilidade e recuperação.
Observabilidade: logs, métricas, tracing e monitoramento.
Segurança: autenticação, autorização, rate limiting e proteção de APIs.
Ainda estou no processo de aprofundar esses conceitos, mas uma das coisas que mais chamou minha atenção é que System Design não é sobre encontrar uma arquitetura perfeita.
É sobre entender os requisitos, identificar restrições e tomar decisões conscientes considerando os trade-offs envolvidos.
Conclusão
Para mim, estudar System Design representa uma mudança de perspectiva.
Como desenvolvedor, é natural pensar primeiro em código: classes, funções, endpoints, componentes e bancos de dados.
System Design força uma visão mais ampla.
Antes de perguntar “como vou implementar isso?”, começamos a perguntar:
“Como esse sistema precisa funcionar?”
“Quais problemas podem aparecer quando ele crescer?”
“Quais decisões arquiteturais fazem sentido para esses requisitos?”
System Design não é apenas desenhar caixas e setas. É entender o problema e tomar boas decisões técnicas diante das restrições existentes.
Top comments (0)