Bancos de dados relacionais x NoSQL: como escolher a base certa para o seu sistema
The choice between a relational and a NoSQL database is one of the most consequential architectural decisions you'll make. Get it right and your system scales gracefully. Get it wrong and you'll be fighting your database for years. This is what you actually need to know.
Todo banco de dados armazena dados. É aí que terminam as semelhanças. Os bancos de dados relacionais e os bancos de dados NoSQL representam filosofias fundamentalmente diferentes sobre como os dados devem ser estruturados, armazenados e consultados — e essas diferenças se refletem em todas as camadas dos sistemas construídos sobre eles.
Não se trata de uma questão de antigo versus novo, ou simples versus sofisticado. Ambas as categorias contêm sistemas maduros e comprovados em produção, utilizados em escala extraordinária. A questão é a adequação à finalidade: qual modelo se adapta à forma dos seus dados, aos padrões de acesso da sua aplicação e às garantias de consistência que seus usuários exigem.
O que realmente é um banco de dados relacional
Um banco de dados relacional organiza os dados em tabelas — linhas e colunas com relações explicitamente definidas entre elas. O termo “relacional” no nome não se refere ao fato de que as tabelas estão relacionadas entre si (embora estejam), mas ao conceito matemático de uma relação: um conjunto de tuplas que compartilham os mesmos atributos. Essa base teórica, desenvolvida por Edgar Codd na IBM em 1970, provou ser notavelmente duradoura.
As principais características de um banco de dados relacional são:
Um esquema fixo. Antes de inserir dados, você define a estrutura: quais tabelas existem, quais colunas cada tabela possui, que tipo de dados cada coluna aceita e quais restrições se aplicam (NOT NULL, UNIQUE, CHECK e assim por diante). O esquema é o contrato entre seu aplicativo e seu banco de dados.
Normalização. Os dados são organizados para eliminar redundâncias. O nome de um cliente aparece uma única vez, na tabela de clientes. Cada pedido faz referência a esse cliente por meio do ID. Se o nome mudar, ele será alterado em um único lugar. Isso não é apenas uma questão de organização — é uma garantia de consistência.
Transações ACID. Atomicidade, Consistência, Isolamento e Durabilidade. Uma transação é concluída na íntegra ou não é concluída de forma alguma. Se você transferir dinheiro de uma conta para outra, o débito e o crédito ocorrem juntos ou nenhum dos dois ocorre. O banco de dados impõe isso no nível do mecanismo.
SQL. A Linguagem de Consulta Estruturada (SQL) é a interface universal para bancos de dados relacionais. É declarativa — você descreve o que deseja, não como obtê-lo — e é extraordinariamente expressiva. Junções, agregações, funções de janela, subconsultas, CTEs: toda a amplitude do SQL oferece ferramentas para fazer perguntas complexas aos seus dados sem precisar escrever código de aplicativo para realizar o trabalho.
Os principais bancos de dados relacionais — PostgreSQL, MySQL, SQL Server, Oracle — compartilham essas propriedades, embora difiram em seus conjuntos de recursos específicos, características de desempenho e modelos de licenciamento. O PostgreSQL, em particular, tornou-se a escolha padrão para novos projetos, combinando estrita conformidade com padrões e um conjunto excepcional de recursos.
O que realmente é um banco de dados NoSQL
“NoSQL” é um termo abrangente que engloba várias categorias distintas de bancos de dados, unidas principalmente pelo que não são: não são relacionais e não usam SQL como interface principal (embora alguns suportem linguagens de consulta semelhantes ao SQL). O termo é melhor compreendido como “não apenas SQL” — um reconhecimento de que o modelo relacional não é a única abordagem válida.
As principais categorias de NoSQL são:
Bancos de dados de documentos armazenam dados como documentos — normalmente JSON ou BSON —, em que cada documento pode ter uma estrutura diferente. O MongoDB é o mais amplamente utilizado; outros incluem o CouchDB e o Firestore. Não há tabelas nem esquema fixo; uma “coleção” de documentos pode conter registros com campos totalmente diferentes.
Armazenamentos de chave-valor são o modelo mais simples: cada registro é um valor endereçável por uma chave única. O Redis é o exemplo dominante, amplamente utilizado para cache, armazenamento de sessão e placares de líderes em tempo real. O DynamoDB também opera principalmente como um armazenamento de chave-valor, com recursos de documentos sobrepostos.
Armazenamentos de famílias de colunas organizam os dados por coluna em vez de por linha, o que permite leituras extremamente eficientes de colunas específicas em milhões de linhas. O Apache Cassandra e o HBase são os principais exemplos. Esse modelo foi projetado para cargas de trabalho com grande volume de gravações e alto volume de dados, nas quais os padrões de consulta são conhecidos antecipadamente.
Bancos de dados de grafos modelam dados como nós e arestas — entidades e as relações entre elas. O Neo4j é o principal exemplo. Quando as relações entre entidades são o tema principal de suas consultas — redes sociais, mecanismos de recomendação, detecção de fraudes —, os bancos de dados de grafos podem expressar essas consultas naturalmente de maneiras que exigiriam SQL profundamente recursivo.
Bancos de dados de séries temporais são otimizados para dados indexados por tempo: InfluxDB, TimescaleDB, Prometheus. Leituras de sensores, tick financeiros, métricas de aplicativos — dados em que o carimbo de data/hora é sempre a chave primária e consultas de intervalo ao longo do tempo são o padrão de acesso dominante.
A diferença estrutural que impulsiona tudo o mais
A diferença mais profunda entre bancos de dados relacionais e NoSQL não é a sintaxe ou a escala — é a relação entre a estrutura de dados e a flexibilidade de consulta.
Os bancos de dados relacionais oferecem máxima flexibilidade de consulta em troca de disciplina de esquema desde o início. Como os dados são normalizados e tipados, você pode fazer praticamente qualquer pergunta sobre eles no momento da consulta. Você pode unir tabelas de maneiras que nunca imaginou ao projetar o esquema. Você pode agregar dimensões que adicionou meses após o projeto inicial. O esquema restringe os dados, mas a linguagem de consulta oferece liberdade.
Os bancos de dados NoSQL fazem a troca oposta. Eles oferecem flexibilidade na forma de estruturar e gravar dados, em troca de padrões de consulta mais restritos. Um banco de dados de documentos permite armazenar dados de qualquer formato sem a necessidade de migração. Mas consultar documentos de forma eficiente requer conhecer seus padrões de acesso com antecedência e projetar sua estrutura de dados em torno deles.
Essa é a tensão central: flexibilidade do esquema versus flexibilidade de consulta. Você pode ter ambas, mas apenas até certo ponto. O modelo de banco de dados que você escolher reflete qual compromisso é mais aceitável para o seu caso de uso.
O teorema CAP e por que ele é importante
Sistemas distribuídos não podem garantir simultaneamente Consistência, Disponibilidade e Tolerância à Partição — eles podem alcançar, no máximo, dois dos três. Esse é o teorema CAP, e é a base teórica para entender por que bancos de dados relacionais e NoSQL se comportam de maneira diferente em condições de falha.
Os bancos de dados relacionais tradicionalmente priorizam a Consistência e a Tolerância à Partição. Cada leitura reflete a gravação mais recente. Se ocorrer uma partição de rede e o banco de dados não puder garantir a consistência, ele se recusará a fornecer dados desatualizados — ele se tornará indisponível em vez de incorreto.
Muitos bancos de dados NoSQL — particularmente aqueles projetados para distribuição horizontal, como Cassandra e DynamoDB — priorizam a disponibilidade e a tolerância à partição. Eles fornecerão dados mesmo durante uma partição de rede, aceitando que algumas leituras possam retornar valores desatualizados. Isso é “consistência eventual”: todos os nós convergirão para o mesmo valor eventualmente, mas há um intervalo durante o qual eles podem não estar de acordo.
A implicação prática: se sua aplicação não pode tolerar a leitura de dados desatualizados — um saldo bancário, uma contagem de estoque, um prontuário médico — você precisa de consistência forte. Se sua aplicação puder tolerar uma breve inconsistência em troca de estar sempre disponível — um feed de mídia social, um catálogo de produtos, um perfil de usuário — a consistência eventual é aceitável e oferece liberdade arquitetônica.
Exemplos do mundo real: quando a escolha certa fez a diferença
GitHub: PostgreSQL no centro de uma plataforma global
O GitHub opera uma das maiores plataformas de colaboração de software do mundo no PostgreSQL — milhões de repositórios, bilhões de eventos, consultas relacionais complexas entre usuários, organizações, repositórios, pull requests, issues e comentários. O modelo relacional se encaixa no domínio: as relações entre essas entidades são o produto. Uma solicitação de pull pertence a um repositório, criada por um usuário, revisada por outros usuários, fechando issues e acionando pipelines de CI.
Durante anos, o GitHub operou uma única instância primária do PostgreSQL com réplicas de leitura. À medida que a escala cresceu, eles introduziram o Vitess (uma camada de particionamento do MySQL para algumas cargas de trabalho) e o ProxySQL para gerenciamento de conexões — mas o núcleo relacional permaneceu. A lição não é que o PostgreSQL escala infinitamente sem esforço. É que o modelo relacional era o mais adequado para um domínio definido por relações, e o esforço investido em escalá-lo valeu a pena precisamente porque migrar para um modelo de dados diferente teria sido mais caro.
Twitter: a migração dolorosa do MySQL para uma arquitetura mista
O Twitter começou com o MySQL e enfrentou uma crise de escalabilidade bem documentada, à medida que o crescimento do número de usuários ultrapassou a capacidade de atendimento de um único banco de dados relacional. O problema central era o gráfico social — as relações de seguidores/seguidos entre centenas de milhões de usuários — e o problema de fanout da linha do tempo: quando um usuário com 10 milhões de seguidores tuíta, esse tuíte precisa aparecer em 10 milhões de linhas do tempo quase instantaneamente.
O modelo relacional, da forma como o Twitter o havia implementado, não conseguia atender a essa disseminação de gravação na velocidade necessária. O Twitter migrou o gráfico social para um armazenamento personalizado na memória e, por fim, adotou o Manhattan (seu armazenamento distribuído interno de chave-valor) para as linhas do tempo e o Cassandra para outras cargas de trabalho com alto volume de gravação.
A lição aqui é sutil. Os dados centrais do Twitter — tweets, usuários, relações — são fundamentalmente relacionais. O problema não era o modelo de dados; era o volume de gravação e a disseminação em uma escala que exigia distribuição. A migração foi cara, tecnicamente complexa e exigiu anos de investimento em engenharia. Na escala do Twitter, foi a decisão certa. Na escala de quase qualquer outro aplicativo, teria sido prematuro.
MongoDB: uma lição sobre a flexibilidade do esquema
No início da década de 2010, à medida que o MongoDB crescia rapidamente em popularidade, muitas equipes o adotaram principalmente por sua flexibilidade de esquema — a capacidade de começar a armazenar dados sem definir um esquema primeiro. Para prototipagem e desenvolvimento em estágio inicial, isso realmente acelerou a iteração.
Os problemas surgiram à medida que os sistemas amadureciam. Sem a imposição de esquema, a inconsistência de dados se acumulava gradualmente. Campos que deveriam ser obrigatórios às vezes estavam ausentes. Valores que deveriam ser inteiros às vezes eram strings. Consultas que presumiam uma estrutura consistente retornavam resultados inesperados. As equipes se viram escrevendo validações extensas no nível do aplicativo que o banco de dados teria imposto gratuitamente.
Isso não é uma falha do MongoDB como banco de dados — ele é uma ferramenta adequada para muitos casos de uso. É uma falha da suposição de que a flexibilidade de esquema é incondicionalmente boa. A flexibilidade adiou o custo de pensar na estrutura de dados; ela não eliminou esse custo. Equipes que usavam o MongoDB sem disciplina acabaram implementando uma versão fraca de um esquema relacional no código da aplicação, sem as garantias que um banco de dados relacional teria fornecido.
Amazon DynamoDB: uma história de sucesso para o caso de uso certo
O carrinho de compras da Amazon é um dos exemplos canônicos de NoSQL bem feito. Os requisitos eram claros: o carrinho de compras precisava estar sempre disponível (um cliente deveria sempre poder adicionar itens, mesmo durante uma falha regional), precisava lidar com um volume massivo de gravações (centenas de milhões de usuários adicionando e removendo itens) e o padrão de acesso era simples e conhecido de antemão (sempre acessado por ID do cliente).
A equipe de engenharia da Amazon, no artigo de 2007 que inspirou o DynamoDB, descreveu a escolha deliberada da consistência eventual para o carrinho: se dois dispositivos adicionassem itens simultaneamente durante uma partição de rede, ambas as adições seriam preservadas quando a partição fosse reparada, mesmo que isso significasse mostrar brevemente um estado ligeiramente inconsistente. Um carrinho de compras que está sempre pronto para gravação — mesmo que isso implique uma breve inconsistência — é mais valioso do que um carrinho que às vezes fica indisponível.
O design do DynamoDB em torno desse caso de uso — acesso simples de chave-valor, padrões de consulta conhecidos, disponibilidade em vez de consistência — é o que o torna excelente. Aplicativos que tentam usar o DynamoDB como um banco de dados relacional de uso geral, executando consultas complexas em várias entidades, enfrentam dificuldades rotineiras.
Airbnb: Elasticsearch para pesquisa, PostgreSQL para verificação
A pesquisa do Airbnb — filtrando anúncios por localização, datas, preço, comodidades e disponibilidade — é uma consulta que nenhum banco de dados relacional consegue atender com eficiência em escala. A combinação de pesquisa geográfica, correspondência de texto completo e filtragem complexa com múltiplos atributos em milhões de anúncios é precisamente o caso de uso para o qual o Elasticsearch foi projetado.
O Airbnb usa o Elasticsearch como camada de pesquisa, mantendo o PostgreSQL como sistema de registro. Quando um anúncio é atualizado, a alteração é gravada no PostgreSQL (a fonte de verdade, com garantias ACID completas) e, em seguida, propagada de forma assíncrona para o Elasticsearch (o índice de pesquisa, otimizado para os padrões de consulta específicos da experiência de pesquisa).
Esse é um padrão arquitetônico maduro: usar o banco de dados certo para cada necessidade, manter uma fonte de verdade clara e aceitar a complexidade operacional de manter vários repositórios sincronizados. Funciona porque os limites são claros e as compensações são compreendidas.

Quando escolher um banco de dados relacional
Um banco de dados relacional é a opção padrão adequada para a maioria das aplicações. Os casos em que é claramente a escolha certa:
Seus dados têm relações significativas. Se as entidades em seu sistema se relacionam entre si de maneiras relevantes — usuários e suas postagens, pedidos e seus itens, projetos e suas tarefas —, o modelo relacional representa essas relações diretamente e permite que você faça consultas entre elas com eficiência.
Você precisa de forte consistência. Transações financeiras, gestão de estoque, sistemas de reservas, registros de saúde — qualquer domínio em que uma leitura incorreta tenha consequências reais requer garantias ACID. Um banco de dados relacional oferece isso no nível do mecanismo.
Seus padrões de consulta não são totalmente conhecidos. Se sua aplicação precisará responder a perguntas sobre seus dados que você não pode antecipar totalmente no momento do projeto, a flexibilidade do SQL é valiosa. A capacidade de escrever uma consulta ad hoc contra um esquema bem normalizado é um ativo operacional significativo.
Sua equipe conhece SQL. Isso pode parecer trivial, mas não é. O SQL é uma das habilidades técnicas mais amplamente compreendidas na engenharia de software. Todo desenvolvedor que você contratar terá algum conhecimento sobre ele. O conhecimento operacional — como adicionar um índice, como ler um plano de consulta, como gerenciar backups — está amplamente disponível. O ecossistema de ferramentas é maduro.
Você não tem certeza do que precisa. Em caso de dúvida, comece com o PostgreSQL. É mais fácil introduzir um armazenamento especializado posteriormente, depois de entender seus padrões de acesso reais, do que migrar de um armazenamento de documentos de volta para um modelo relacional quando seus dados se revelarem mais estruturados do que você imaginava.
Quando escolher NoSQL
NoSQL é a escolha certa quando um requisito específico não pode ser atendido pelo modelo relacional sem um esforço desproporcional:
O volume de gravações excede o que um único nó pode suportar. Se sua aplicação precisa sustentar centenas de milhares de gravações por segundo em um sistema geograficamente distribuído, o escalonamento horizontal por muitos nós torna-se necessário. Armazenamentos de famílias de colunas, como o Cassandra, são projetados para isso; bancos de dados relacionais podem ser distribuídos, mas esse não é seu modo natural.
Seus dados são genuinamente sem esquema ou altamente variáveis. Um catálogo de produtos onde diferentes tipos de produtos têm atributos totalmente distintos, um CMS onde os tipos de conteúdo evoluem rapidamente, um sistema de log onde esquemas de eventos são definidos por sistemas externos — esses casos se beneficiam do armazenamento de documentos, onde a estrutura não é imposta pelo banco de dados.
Seu padrão de acesso principal é a pesquisa de chave-valor em escala extrema. Armazenamentos de sessão, caches, tabelas de classificação em tempo real, sinalizadores de recursos — cargas de trabalho nas quais você sempre acessa dados por uma única chave e nunca precisa fazer junções ou agregações se beneficiam da simplicidade e do desempenho de um armazenamento de chave-valor.
Você está modelando um grafo. Se suas consultas principais envolvem percorrer relações — encontrar todos os amigos de amigos, identificar o caminho mais curto entre dois nós, detectar dependências circulares —, um banco de dados de grafos expressará essas consultas de forma mais natural e as executará com mais eficiência do que o SQL recursivo.
Você precisa de otimização de séries temporais. Milhões de leituras de sensores, tick financeiros ou métricas de aplicativos por segundo, com consultas principalmente sobre intervalos de tempo, são melhor atendidas por um banco de dados de séries temporais desenvolvido especificamente para esse fim do que por um banco de dados relacional com uma coluna de carimbo de data/hora.
A realidade do uso de múltiplos bancos de dados
O mais importante a entender sobre a questão relacional versus NoSQL é que, na maioria dos sistemas maduros, não se trata de uma escolha do tipo “ou isso ou aquilo”. Sistemas em escala utilizam rotineiramente múltiplos bancos de dados, cada um escolhido para a carga de trabalho específica que atende.
PostgreSQL para o sistema de registro. Redis para cache de sessão e limitação de taxa. Elasticsearch para pesquisa de texto completo. InfluxDB para métricas de aplicativos. Cada banco de dados nessa pilha está fazendo o que faz de melhor, e a camada de aplicativos gerencia a consistência entre eles.
O custo operacional dessa complexidade é real. Cada banco de dados adicional é mais um sistema para monitorar, fazer backup, escalar e entender. A disciplina de engenharia necessária para manter a consistência entre vários armazenamentos — lidando com cenários de falha em que uma gravação no PostgreSQL é bem-sucedida, mas a atualização subsequente no Elasticsearch falha — não é trivial.
O ponto de partida para quase todas as aplicações deve ser um único banco de dados relacional. Adicione armazenamentos especializados quando um requisito específico e bem compreendido não puder ser atendido sem eles. A diversificação prematura de bancos de dados é uma forma de otimização prematura: ela adiciona complexidade antes que você compreenda se essa complexidade é necessária.

Tomando a decisão
As perguntas que realmente importam ao escolher um banco de dados:
Quais são seus requisitos de consistência? Se a resposta para “o que acontece se um usuário ler dados desatualizados” for “isso é um problema sério”, você precisa de ACID. Se a resposta for “isso é um pouco incômodo, mas aceitável”, você tem opções.
Quais são seus padrões de consulta? Se você sabe exatamente como seus dados serão acessados e esse padrão de acesso é simples e de alto volume, você pode otimizar para ele. Se seus padrões de acesso são complexos ou não totalmente conhecidos, a flexibilidade do SQL é valiosa.
Qual é o seu volume de gravação? Para a grande maioria das aplicações, uma instância do PostgreSQL bem ajustada em hardware razoável lida com milhares de gravações por segundo sem dificuldade. Os casos em que isso é realmente insuficiente são mais raros do que o hype do NoSQL da década de 2010 sugeria.
Qual é a forma dos seus dados? Dados altamente uniformes e fortemente relacionados se encaixam bem no modelo relacional. Dados altamente variáveis e vagamente relacionados podem se encaixar melhor em um modelo de documento.
O que sua equipe sabe? A familiaridade operacional é importante. Uma equipe que conhece profundamente o PostgreSQL construirá um sistema mais confiável no PostgreSQL do que em um banco de dados NoSQL que está aprendendo, mesmo que o banco de dados NoSQL seja teoricamente mais adequado.
O banco de dados relacional sobreviveu a cinquenta anos de mudanças tecnológicas não porque seja sempre a melhor ferramenta, mas porque é um padrão excepcionalmente bom — flexível, confiável, bem compreendido e respaldado por décadas de conhecimento operacional. Desvie-se dele deliberadamente, com uma compreensão clara do que você ganha e do que abre mão.