# Relational vs NoSQL

> Key-value, document, wide-column and graph stores compared with a relational database.

Concept · Storage & databases · https://levelcode.org/concepts/sql-vs-nosql

"NoSQL" covers several unrelated designs whose common feature is that they aren't relational. Each gives up some of what a relational database offers in exchange for something specific.

| Type | Examples | Data model | Gives you | Gives up |
|---|---|---|---|---|
| Relational | PostgreSQL, MySQL | Tables, rows, joins | Flexible queries, transactions, constraints | Easy horizontal write scaling |
| Key-value | Redis, DynamoDB, etcd | Value by key | Very fast, simple, scalable lookups | Queries by anything but the key |
| Document | MongoDB, Firestore | JSON-like documents | Nested, variable-shape entities read as a whole | Joins and many-to-many relationships |
| Wide-column | Cassandra, ScyllaDB, Bigtable | Partitions of sorted rows | Huge write throughput, linear scaling, multi-region | Ad-hoc queries; one table per query pattern |
| Graph | Neo4j, Neptune | Nodes and edges | Fast multi-hop traversals | General-purpose querying and scale-out |

## The real differences

- **Who knows the queries?** Relational databases let you add queries and indexes later. Key-value and wide-column stores require you to design keys around known queries up front; a new query often means a new table.
- **Transactions.** Relational databases give multi-row, multi-table transactions. Many NoSQL stores limit atomicity to one item or one partition (some, like DynamoDB and MongoDB, now offer multi-item transactions with limits and costs).
- **Scaling model.** Wide-column and key-value stores partition data across nodes by design; relational databases scale up first and partition with more effort.
- **Schema.** "Schemaless" means the schema lives in application code. You still have one; it's just not enforced.

## A sensible default

Start relational. PostgreSQL's `jsonb` covers variable-shape data, and a single node goes a long way. Choose a NoSQL store when a requirement points at it: write volume beyond one machine, a pure key-value access pattern at very high scale, or a data model (deep graph traversal) that relational queries handle badly. See [normalization vs denormalization](https://levelcode.org/concepts/normalization-vs-denormalization) and the System Design roadmap's datastore lesson.
