é o processo de definir a arquitetura, componentes, módulos, interfaces e dados de um sistema para atender a requisitos específicos. é a ponte entre a teoria da ciência da computação e a prática de construir sistemas robustos e escaláveis.

enquanto a arquitetura de software foca na estrutura interna e padrões de código, o system design foca na infraestrutura, comunicação entre componentes e trade-offs em larga escala.

pilares do system design

escalabilidade

é a capacidade do sistema de crescer e lidar com mais carga.

  • vertical (scale up): adicionar mais poder (CPU/RAM) a uma única máquina.
    • pró: simples.
    • contra: limite físico e SPOF (single point of failure)
  • horizontal (scale out): adicionar mais máquinas ao pool de recursos.
    • pró: escalabilidade quase ilimitada
    • contra: complexidade de gerenciamento

load balancing

componente crítico para escalabilidade horizontal. distribui o tráfego de rede entre vários servidores para garantir que nenhum fique sobrecarregado.

  • algoritmos comuns: round robin, least connections, IP hash.
  • pode atuar na Camada 4 (transporte/TCP) ou camada 7 (aplicação/HTTP).

caching

armazenar dados acessados frequentemente em memória (rápida) para reduzir a carga no banco de dados (lento).

  • locais: browser, CDN, API Gateway, banco de dados
  • ferramentas: Redis, Memcached.
  • desafio: invalidação de cache

"existem apenas duas coisas difíceis na ciência da computação: invalidação de cache e nomear as coisas" — Phil Karlton

bancos de dados e persistência

a escolha entre SQL (relacional) e NoSQL (não-relacional) define a flexibilidade e a consistência do sistema.

  • replication: master-slave (leitura escala, escrita centralizada) vs. master-master
  • sharding: dividir o banco em pedaços menores distribuídos em servidores diferentes
  • teorema CAP: em um sistema distribuído, você só pode ter 2 de 3:
    • consistency: todos vêem os mesmos dados ao mesmo tempo.-
    • availability: o sistema sempre responde (mesmo com dados velhos)
    • partition tolerance: o sistema funciona mesmo se a rede falhar

    na prática, em sistemas distribuídos, P é obrigatório, então a escolha é entre CP (bancos fortes como Postgres) ou AP (bancos flexíveis como Cassandra/Dynamo).

comunicação

como os serviços conversam entre si. pode ser síncrona ou assíncrona.

  • síncrona (blocking): HTTP/REST, gRPC, GraphQL. o cliente espera a resposta
  • assíncrona (non-blocking): message queues (RabbitMQ, Kafka) e event-driven architecture. o cliente envia e segue a jprnada; o processamento ocorre em background. é e essencial para desacoplamento e load leveling.

framework para decisões

requisitos

  • funcionais: o que o sistema faz?
  • não-funcionais: qual a latência aceitável? quantos usuários simultâneos (DAU/MAU)? consistência ou disponibilidade?

estimativas (back-of-the-envelope)

  • cálculo rápido de armazenamento e banda de rede necessários./

high-level desigm

desenhar as grandes caixas (ex: LB Web Server DB)

design detalhado

aprofundamento nos gargalos. (como escalar o banco? como lidar com falhas?)

identificar gargalos

onde o sistema vai quebrar primeiro? (SPOFs, latência de rede)

a regra de ouro

mantenha simples até que precise ser complexo. tudo na arquitetura de software é um trade-off.