Como escolher, escalar e pensar além do CRUD
Alex Seixas
Senior Software Engineer · Engineering Manager
Sou engenheiro de software atuando em produtos e times internacionais, com experiência prática em arquitetura de sistemas, banco de dados, performance, escalabilidade e desenvolvimento de aplicações para diferentes contextos de negócio.
Hoje trabalho como Senior Software Engineer em projetos para Portugal e Canadá e também atuo como Engineering Manager em uma operação nos Estados Unidos, liderando iniciativas técnicas, decisões de arquitetura e evolução de produtos.
Nesta aula, a proposta é trazer uma visão de banco de dados que vai além do CRUD: conectando modelagem, consistência, escalabilidade, sistemas distribuídos e trade-offs reais de arquitetura.
"Escolho pelo tipo de dado"
Relacional para estruturado, documento para flexível, cache para rápido...
Não. O tipo importa, mas está longe de ser o único critério.
Consistência, latência, escala e operação pesam tanto quanto o modelo.
A pergunta correta não é "qual banco eu gosto?"
A pergunta correta é "quais atributos meu sistema precisa ter?"
Modelo tabular com SQL, joins, constraints e transações ACID
Casos de uso
ACID
Forte consistência transacional
JSONB
Dados semi-estruturados
Extensível
Tipos, funções, extensões
Índices
B-tree, GIN, GiST, Hash
CTEs & Views
Consultas complexas
Replicação
Ecossistema maduro
Excelente default para a maioria dos produtos com dados estruturados.
É outra categoria de trade-offs, não um upgrade natural.
Document DBs
MongoDB, Couchbase
Key-Value
Redis, DynamoDB
Wide-Column
Cassandra, ScyllaDB
Graph DBs
Neo4j, Neptune
Search Engines
Elasticsearch, OpenSearch
Time-Series
InfluxDB, Prometheus
Vector DBs
Pinecone, Weaviate
Event Stores
EventStoreDB, Kafka
Quando faz sentido
Atenção
Flexibilidade não elimina modelagem. Joins complexos e relacionamentos profundos podem ficar ruins.
Casos de uso
Trade-off
Velocidade altíssima, mas geralmente com menos poder relacional e consultivo.
Workloads típicos
Logs, eventos, telemetria, timelines com grandes volumes de escrita e leitura distribuída.
Nós e relacionamentos — ótimo para conexões complexas.
Importante
Search engine normalmente não substitui o banco transacional principal.
Dados orientados ao tempo — cada registro carrega um timestamp como dimensão central.
Métricas
Observabilidade e monitoramento
IoT
Sensores e telemetria
Eventos
Séries temporais com agregação
Guardam embeddings — representações numéricas do significado de um texto ou imagem. A busca encontra conteúdo parecido, não apenas idêntico.
A busca deixa de ser "igualdade exata" e passa a ser "proximidade semântica".
Event Sourcing = guardar cada mudança que aconteceu, não só o resultado final. Como um extrato bancário, não apenas o saldo atual.
Estado atual
Guarda o valor agora: saldo = R$ 500
Histórico de eventos
Guarda tudo que aconteceu: depósito, saque, transferência...
Ideia central: Event Sourcing
Deixa de ser "uma tabela em um servidor" e passa a fazer parte de uma arquitetura distribuída.
Copiar os dados do banco principal para outras máquinas. Serve para ler mais rápido, fazer backup e continuar funcionando se o principal cair.
Replication lag = a cópia demora para receber a atualização. Você escreve no primário, lê na réplica e pode ver dado antigo por alguns segundos.
Replication lag
Seu sistema tolera esse atraso ou não?
Os servidores não ficam iguais na hora, mas depois de um tempo todos convergem. Aceitável quando ver dado levemente desatualizado não é um problema grave.
"Nem todos os nós enxergam o mesmo dado imediatamente, mas o sistema converge depois."
Feed social
Curtidas e analytics
Tracking
Notificações
Dashboards não críticos
Todo mundo precisa ver o mesmo valor ao mesmo tempo. Quando errar por segundos causa prejuízo real — dinheiro, estoque ou vaga perdida.
Saldo bancário
Pagamento
Estoque crítico
Reserva de assento
Antifraude transacional
Transações financeiras
Nesses cenários, "eventualmente correto" pode ser tarde demais.
A rede quebra no meio e dois grupos de servidores ficam isolados — cada um continua funcionando, mas não conseguem conversar entre si.
Quando a rede falha, você não consegue garantir dado 100% correto e sistema sempre respondendo ao mesmo tempo. Precisa escolher um lado.
C
Consistency
Todos veem o mesmo dado
A
Availability
Sistema sempre responde
P
Partition Tolerance
Tolera falha de rede
Em um sistema distribuído, diante de partição de rede, não é possível garantir consistência forte e disponibilidade total ao mesmo tempo.
CAP não é uma escolha permanente de configuração — é a decisão que você toma no momento em que a rede falha.
CAP não significa "escolha 2 para sempre".
Quando a rede falha, você precisa decidir qual lado sacrificar.
CP prefere parar ou bloquear a entregar dado errado. AP prefere continuar respondendo, mesmo que o dado ainda não esteja atualizado.
CP — Consistency + Partition
Ex.: ZooKeeper, etcd, HBase
AP — Availability + Partition
Ex.: Cassandra, DynamoDB, Couchbase
CAP olha o que acontece quando a rede falha. PACELC lembra que, mesmo sem falha, você troca velocidade por dado mais fresco.
Se houver partição (P)
Availability ou Consistency?
Else — sem partição
Latency ou Consistency?
Mesmo sem falha, sistemas distribuídos vivem trade-offs entre latência e consistência.
Ler do servidor mais próximo é rápido, mas o dado pode estar desatualizado. Ler do servidor central é mais lento, porém mais confiável.
Resposta rápida
Ler da região mais próxima ao usuário
Menor latência, dado pode estar desatualizado
Dado mais atualizado
Buscar na região central / primária
Maior latência, maior consistência
Sharding = dividir os dados em pedaços menores e guardar cada pedaço em um servidor diferente. É como separar clientes por andares em vez de colocar todos num único prédio — escala, mas complica consultas e operação.
Sharding ajuda escala, mas aumenta complexidade de roteamento, rebalanceamento, queries e operação.
Atalho que o banco usa para achar linhas sem varrer a tabela inteira — como o índice de um livro. Acelera leitura, mas deixa escrita e armazenamento mais pesados.
Tipos comuns
Garantias de que uma operação composta completa tudo corretamente ou não faz nada. Essencial em transferências, pagamentos e qualquer regra de negócio crítica.
A
Atomicity
Tudo ou nada
C
Consistency
Regras válidas
I
Isolation
Sem interferência
D
Durability
Persiste após commit
ACID prioriza correção rigorosa. BASE prioriza ficar online e aceitar que os dados convergem depois — comum em sistemas de grande escala.
ACID
Bancos relacionais, pagamentos
BASE
Feeds, analytics, cache distribuído
Normalizar = organizar tabelas para não repetir dados. Desnormalizar = repetir dados de propósito para evitar joins e ler mais rápido.
Normalização
Desnormalização
Nenhuma é "sempre correta" — depende do workload.
OLTP = banco do dia a dia do app — muitas operações pequenas e rápidas. OLAP = banco de análise — consultas pesadas, relatórios e dashboards.
OLTP
OLAP
Copia dados do banco do app para um ambiente feito para consultas pesadas. Relatórios e BI rodam lá — sem travar o sistema que o usuário usa no dia a dia.
Analytics pesado nem sempre deve rodar no banco transacional principal.
Usar mais de um banco no mesmo sistema — cada um resolve um problema diferente. Não é fraqueza; é escolher a ferramenta certa para cada job.
PostgreSQL
Transações
Redis
Cache
Elasticsearch
Busca
S3
Arquivos
BigQuery
Analytics
pgvector
IA / embeddings
O problema define o banco, não o contrário.
E-commerce pequeno
PostgreSQL + Redis
Feed social / timeline
Wide-column + cache + eventos
Busca em catálogo
PostgreSQL + Elasticsearch
IA com documentos
PostgreSQL + pgvector
"Sempre escolha o banco de dados de acordo com os atributos que você quer que seu sistema tenha."
Banco de Dados para Desenvolvedores