Relational vs non-relational databases: the real comparison
Now that SELECT / WHERE / JOIN click, the next question is why entire categories of databases exist that skip tables altogether — and when that trade actually pays off.
A relational database (SQL database — Postgres, MySQL, SQLite) stores data in tables with a fixed schema: every row in a table has the same columns, and tables relate to each other through foreign keys (a user_id column in an orders table pointing back to the users table). The word "relational" refers to those relationships between tables, not to relationships between people or objects in your app.
The engine enforces the schema at write time. If a column is defined as an integer, the database rejects a write that tries to put text in it. If you delete a user, a foreign key constraint can stop you from leaving orphaned orders behind. That enforcement is the whole value proposition: consistency is guaranteed by the database itself, not by application code remembering to check.
2. What "non-relational" covers — it's not one thing
Non-relational (commonly called NoSQL, though the name is a historical accident more than an accurate description) is an umbrella term for databases that don't organize data as rows in fixed-schema tables. That's the only thing they all have in common — under that umbrella sit at least four genuinely different data models, each solving a different problem.
The naming trap: "NoSQL" makes it sound like one alternative to SQL. It isn't. Document stores, key-value stores, wide-column stores, and graph databases have almost nothing in common with each other beyond "not relational tables." Comparing "SQL vs NoSQL" as if it were a single choice is the most common mistake in this conversation.
3. The core trade-off: structure vs flexibility
Relational
Non-relational
Fixed schema, enforced by the database
Flexible or no schema — enforcement (if any) happens in application code
Strong consistency by default (ACID transactions)
Often trades strict consistency for availability and speed at scale
Joins across tables are a first-class operation
Data is usually denormalized — related data is duplicated inside one record to avoid joins
Scales vertically first, horizontally with more effort (sharding)
Many were built horizontal-scaling-first, distributing across many machines by design
Best fit: data with clear, stable relationships
Best fit: data that's naturally nested, high-volume, or schema-varies-per-record
Neither column is "better" in the abstract. The trade-off is real: rigid structure buys you correctness guarantees and powerful querying across relationships; flexible structure buys you a shape that matches your data more naturally and can scale out more easily, at the cost of pushing consistency checks into your application.
4. The main types of non-relational databases
Type
Stores data as
Examples
Typical use
Document
JSON-like documents, each can have a different shape
MongoDB, Firestore, Couchbase
Content with nested, variable structure — user profiles, product catalogs, CMS content
Key-value
A key mapped to an opaque value, no query language into the value itself
Redis, DynamoDB, Memcached
Caching, session storage, feature flags — anything needing extremely fast lookups by a known key
Wide-column
Rows with a huge, sparse, flexible set of columns, optimized for massive scale
Cassandra, HBase, Bigtable
Time-series data, IoT telemetry, write-heavy workloads at enormous scale
Graph
Nodes and edges, where the relationships themselves are first-class data
Neo4j, Amazon Neptune
Social networks, recommendation engines, fraud detection — anything where "how things connect" is the actual question
Notice the irony: graph databases are, in a sense, more relationship-focused than relational databases — they just model relationships as direct pointers between records instead of foreign keys resolved through joins.
5. When relational wins
Money and transactions. ACID guarantees (a transfer either fully completes or fully rolls back) matter more than raw write throughput. This is why nearly every payments and accounting system runs on a relational database.
Data with real, queryable relationships. If you regularly need to ask "give me all orders from users in this region who bought this product," joins across normalized tables are the natural tool for that question.
You want the database to catch your mistakes. Schema enforcement and foreign key constraints turn a class of bugs (orphaned records, wrong data types) into errors at write time instead of silent corruption discovered months later.
6. When non-relational wins
The shape of your data varies per record. A product catalog where some items have five attributes and others have fifty doesn't want a rigid table schema — a document store lets each record be its own shape.
You need extremely fast, simple lookups. A cache hit ("give me the value for this session ID") doesn't need a query planner or joins — a key-value store answers it in microseconds.
Write volume is massive and horizontal scale is the priority. Systems ingesting millions of events per second (sensor data, logs, analytics events) often lean on wide-column stores built to distribute across many machines from day one.
The question is literally about connections. "Who are this person's second-degree connections" is a graph traversal — expressing that as SQL joins gets slow and unwieldy fast; a graph database answers it directly.
7. Can you use both? Polyglot persistence
Yes, and most non-trivial systems already do, whether or not the team calls it that. A common pattern: Postgres (relational) as the source of truth for users, orders, and billing, Redis (key-value) as a cache in front of it, and maybe Elasticsearch (a specialized search-oriented store) for full-text search over product descriptions. This is called polyglot persistence — using the right storage engine per problem instead of forcing every use case through one database.
The catch: every additional data store is another system to operate, another place data can get out of sync, and another thing a new engineer has to learn. Polyglot persistence is a real technique, not a default — reach for a second database engine when a specific access pattern genuinely doesn't fit the first one, not because the option exists.
8. A practical example
Take an e-commerce app. Orders, payments, and inventory counts — data with strict consistency needs and clear relationships — sit naturally in Postgres. Product search-as-you-type benefits from a search-optimized store. The shopping cart, which needs to be read and written on almost every page load but tolerates being lost if a user never checks out, is a textbook Redis use case. None of these choices contradicts the others; each one matches a specific access pattern to the storage engine built for it.
The question to ask for any new piece of data isn't "SQL or NoSQL" in the abstract — it's "does this data have a fixed shape, does it need transactional guarantees, and how is it actually going to be queried." The answer to those three questions almost always points you to the right category on its own.
Share:
Newsletter
Learn what AI is creating for you. Don't get lost.
Get notified when a new deep dive or lesson goes up. No spam, just new posts.
Lição 12 · Dados e backend
Bancos relacionais vs não-relacionais: a comparação de verdade
Agora que SELECT / WHERE / JOIN fizeram sentido, a próxima pergunta é por que existem categorias inteiras de banco de dados que abandonam tabelas de vez — e quando essa troca realmente vale a pena.
Um banco de dados relacional (banco SQL — Postgres, MySQL, SQLite) guarda dados em tabelas com esquema fixo: toda linha de uma tabela tem as mesmas colunas, e as tabelas se relacionam entre si por chaves estrangeiras (uma coluna user_id numa tabela orders apontando de volta pra tabela users). A palavra "relacional" se refere a essas relações entre tabelas, não a relações entre pessoas ou objetos da sua aplicação.
O motor do banco aplica o esquema no momento da escrita. Se uma coluna é definida como número inteiro, o banco rejeita uma escrita que tente colocar texto ali. Se você deleta um usuário, uma restrição de chave estrangeira pode te impedir de deixar pedidos órfãos. Essa aplicação de regra é toda a proposta de valor: consistência garantida pelo próprio banco, não por código de aplicação que precisa lembrar de checar.
2. O que "não-relacional" cobre — não é uma coisa só
Não-relacional (comumente chamado de NoSQL, embora o nome seja mais um acidente histórico que uma descrição precisa) é um termo guarda-chuva pra bancos que não organizam dados como linhas em tabelas de esquema fixo. Isso é a única coisa que todos têm em comum — debaixo desse guarda-chuva ficam pelo menos quatro modelos de dados genuinamente diferentes, cada um resolvendo um problema distinto.
A armadilha do nome: "NoSQL" faz parecer que é uma alternativa única ao SQL. Não é. Bancos de documento, chave-valor, coluna larga e grafo têm quase nada em comum entre si além de "não são tabelas relacionais". Comparar "SQL vs NoSQL" como se fosse uma escolha só é o erro mais comum dessa conversa.
3. O trade-off central: estrutura vs flexibilidade
Relacional
Não-relacional
Esquema fixo, aplicado pelo banco
Esquema flexível ou inexistente — a aplicação (se houver) fica com essa checagem
Consistência forte por padrão (transações ACID)
Frequentemente troca consistência estrita por disponibilidade e velocidade em escala
Joins entre tabelas são uma operação de primeira classe
Dados geralmente desnormalizados — dados relacionados são duplicados dentro de um registro pra evitar joins
Escala verticalmente primeiro, horizontalmente com mais esforço (sharding)
Muitos foram construídos pra escalar horizontalmente desde o início, distribuindo por várias máquinas por design
Melhor encaixe: dados com relações claras e estáveis
Melhor encaixe: dados naturalmente aninhados, de alto volume, ou com esquema variando por registro
Nenhuma coluna é "melhor" no abstrato. O trade-off é real: estrutura rígida compra garantias de correção e consultas poderosas entre relações; estrutura flexível compra um formato que combina mais naturalmente com seus dados e escala mais fácil pra fora, ao custo de empurrar checagens de consistência pra sua aplicação.
4. Os principais tipos de banco não-relacional
Tipo
Guarda dados como
Exemplos
Uso típico
Documento
Documentos parecidos com JSON, cada um pode ter um formato diferente
MongoDB, Firestore, Couchbase
Conteúdo com estrutura aninhada e variável — perfis de usuário, catálogo de produtos, conteúdo de CMS
Chave-valor
Uma chave mapeada a um valor opaco, sem linguagem de consulta dentro do valor
Redis, DynamoDB, Memcached
Cache, armazenamento de sessão, feature flags — qualquer coisa que precise de busca extremamente rápida por uma chave conhecida
Coluna larga
Linhas com um conjunto enorme, esparso e flexível de colunas, otimizado pra escala massiva
Cassandra, HBase, Bigtable
Dados de série temporal, telemetria de IoT, cargas de trabalho pesadas em escrita e em escala enorme
Grafo
Nós e arestas, onde as próprias relações são dados de primeira classe
Neo4j, Amazon Neptune
Redes sociais, motores de recomendação, detecção de fraude — qualquer coisa onde "como as coisas se conectam" é a pergunta real
Note a ironia: bancos de grafo são, em certo sentido, mais focados em relações que bancos relacionais — só modelam relações como ponteiros diretos entre registros em vez de chaves estrangeiras resolvidas por joins.
5. Quando o relacional vence
Dinheiro e transações. Garantias ACID (uma transferência completa inteira ou desfaz inteira) importam mais que taxa bruta de escrita. É por isso que quase todo sistema de pagamentos e contabilidade roda em banco relacional.
Dados com relações reais e consultáveis. Se você precisa regularmente perguntar "me dê todos os pedidos de usuários dessa região que compraram esse produto", joins entre tabelas normalizadas são a ferramenta natural pra essa pergunta.
Você quer que o banco pegue seus erros. Esquema aplicado e restrições de chave estrangeira transformam uma classe de bugs (registros órfãos, tipo de dado errado) em erros no momento da escrita, em vez de corrupção silenciosa descoberta meses depois.
6. Quando o não-relacional vence
O formato dos seus dados varia por registro. Um catálogo de produtos onde alguns itens têm cinco atributos e outros têm cinquenta não quer um esquema de tabela rígido — um banco de documento deixa cada registro ter seu próprio formato.
Você precisa de buscas extremamente rápidas e simples. Um acerto de cache ("me dê o valor pra esse ID de sessão") não precisa de planejador de consulta nem joins — um banco chave-valor responde em microssegundos.
O volume de escrita é massivo e escala horizontal é a prioridade. Sistemas que ingerem milhões de eventos por segundo (dados de sensor, logs, eventos de analytics) frequentemente se apoiam em bancos de coluna larga construídos pra distribuir por várias máquinas desde o dia um.
A pergunta é literalmente sobre conexões. "Quais são as conexões de segundo grau dessa pessoa" é uma travessia de grafo — expressar isso como joins SQL fica lento e desajeitado rápido; um banco de grafo responde direto.
7. Pode usar os dois? Persistência poliglota
Sim, e a maioria dos sistemas não-triviais já faz isso, mesmo que o time não chame por esse nome. Um padrão comum: Postgres (relacional) como fonte da verdade pra usuários, pedidos e cobrança, Redis (chave-valor) como cache na frente dele, e talvez Elasticsearch (um banco especializado em busca) pra busca textual sobre descrições de produto. Isso se chama persistência poliglota — usar o motor de armazenamento certo pra cada problema em vez de forçar todo caso de uso por um banco só.
A pegadinha: cada banco adicional é mais um sistema pra operar, mais um lugar onde dados podem ficar fora de sincronia, e mais uma coisa que um engenheiro novo precisa aprender. Persistência poliglota é uma técnica real, não um padrão a seguir por padrão — recorra a um segundo motor de banco quando um padrão de acesso específico genuinamente não se encaixa no primeiro, não porque a opção existe.
8. Um exemplo prático
Pega um app de e-commerce. Pedidos, pagamentos e contagem de estoque — dados com necessidade estrita de consistência e relações claras — ficam naturalmente no Postgres. Busca de produto enquanto você digita se beneficia de um banco otimizado pra busca. O carrinho de compras, que precisa ser lido e escrito em quase todo carregamento de página mas tolera ser perdido se o usuário nunca finaliza a compra, é um caso de uso de manual pro Redis. Nenhuma dessas escolhas contradiz as outras; cada uma casa um padrão de acesso específico com o motor de armazenamento construído pra ele.
A pergunta a fazer pra qualquer dado novo não é "SQL ou NoSQL" no abstrato — é "esse dado tem formato fixo, precisa de garantias transacionais, e como ele vai ser consultado de fato". A resposta a essas três perguntas quase sempre aponta pra categoria certa por conta própria.
Compartilhar:
Newsletter
Saiba o que a IA está criando pra você. Não fique por fora.
Seja avisado quando eu postar uma imersão ou lição nova. Sem spam, só posts novos.