SYSTEM DESIGN · CONCEPTS · DATABASES · EPISODE 16

SQL vs NoSQL: How to Choose

What a relational database gives you (tables, joins, transactions), what the four NoSQL families give you (flexible shape, scale by key), the myth that NoSQL is faster, and the four questions that pick the right one in an interview.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
1 / 19

Press play to hear the narration, or step through at your own pace. Every picture here is the same one used in the YouTube video.

Notes

What SQL is

Start with what SQL is. A relational database keeps data in tables. Every row has the same columns, and the schema is fixed up front. Postgres and MySQL are the ones you'll name in interviews.

Its first superpower is joins. Users and orders live in separate tables, and one query combines them. You can ask questions nobody planned for when the schema was designed. That flexibility of queries is the point of SQL.

Its second superpower is transactions. Move five hundred rupees from one account to another: two updates, and the database guarantees both happen or neither does, even if the server crashes halfway. That guarantee is called ACID, and it's why money and orders live in SQL.

The cost. A relational database is happiest on one machine. You scale reads with replicas, but spreading writes across many machines, called sharding, is manual work, and once you shard, joins and transactions across shards stop working. That's the real limit, not speed.

A relational table
users
id | name   | email
1  | Priya  | p@x.com
2  | Arjun  | a@x.com

orders
id | user_id | total
7  | 1       | 499
Joins: relationships are built in
SELECT u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.total > 100;

→ any question across tables,
  without planning it in advance
Transactions: all or nothing
BEGIN;
UPDATE accounts SET balance = balance - 500
  WHERE id = 1;
UPDATE accounts SET balance = balance + 500
  WHERE id = 2;
COMMIT;

both happen, or neither (ACID)
The cost
  • one machine holds all the data
  • scale up first: bigger box
  • read replicas help reads
  • splitting writes across machines
  • (sharding) is manual and hard:
  • joins and transactions stop
  • working across shards

What NoSQL is

Now NoSQL. It isn't one thing, it's four families, and the name only says what they're not. Key-value stores like Redis and DynamoDB. Document stores like MongoDB. Wide-column stores like Cassandra. And graph databases like Neo4j.

Key-value is the simplest: give me the value for this key, in one hop. Document stores keep whole records as nested JSON. Two users can have different fields, and the record you read is the record your app uses, no joins needed.

Wide-column stores group rows by a partition key and sort them, which makes them great for massive write volume in time order, like chat messages or sensor data. Graph databases store relationships directly, so friends of friends is one cheap query instead of a chain of joins.

Key-value and document
key-value:
  "session:8f3a" → { user: 1, … }
  one lookup, by key, O(1)

document:
  { id: 2, name: "Arjun",
    addresses: [ … ],
    prefs: { dark: true } }
Wide-column and graph
wide-column:
  partition key: chat_id
  rows sorted by time
  → huge write volume, time-ordered

graph:
  nodes + edges
  → friends of friends, in one query

Why NoSQL scales

Here's why NoSQL scales out easily. Every record has a partition key, and the store uses it to decide which machine owns the record. Writes for different keys go to different machines, so adding machines adds capacity. Sharding is built in, not bolted on.

The cost. There are no joins across partitions, so you must know your access patterns before you design the keys. And many NoSQL stores are eventually consistent by default: read right after a write, and you might see the old value for a moment. You trade query freedom and strict consistency for scale.

The cost
  • no joins across partitions
  • queries must follow the key
  • (know your access pattern first)
  • consistency is often eventual:
  • a read right after a write
  • can return the old value

The myth

Time for the myth. NoSQL is not faster. A well-indexed Postgres handles tens of thousands of queries a second on one machine. A NoSQL store is fast for the exact access pattern it was designed around, and slow, or impossible, for anything else. Speed comes from matching the store to the pattern.

Myth: NoSQL is faster
  • Postgres serves 10k+ queries/sec
  • on one machine, with indexes
  • NoSQL is faster only for the
  • access pattern it was built for
  • wrong pattern → slower than SQL

How to choose

So how do you choose? Ask four questions. One: do records relate to each other, and do I query across them? Two: do I need all-or-nothing updates across several records? Three: will the questions change later, or do I know every query today? Four: is write volume beyond one machine, or is the data naturally nested?

The rule. Yes to relationships, transactions or unknown queries: SQL, and Postgres by default. A known access pattern with huge write volume or a nested shape: NoSQL, and pick the family that fits. If you're unsure, start with Postgres. It's the safe answer, and interviewers know it.

Four questions
  • 1. Do records relate to each other,
  • and do I query across them?
  • 2. Do I need all-or-nothing updates
  • across several records?
  • 3. Will the questions change,
  • or do I know every query today?
  • 4. Is write volume beyond one
  • machine, or is the shape nested?
The rule
  • yes to 1, 2 or 3 → SQL
  • (Postgres by default)
  • known access pattern +
  • huge writes or nested shape
  • → NoSQL
  • unsure → start with Postgres

Examples

Some examples. Orders and payments: SQL, for transactions. User profiles with varying fields: a document store. Sessions and caches: key-value. Chat messages and logs, written constantly in time order: wide-column. A social graph: graph. A URL shortener: key-value, one lookup by code.

Examples
  • orders, payments → SQL
  • user profiles → document
  • sessions, cache → key-value
  • chat messages, logs → wide-column
  • social graph → graph
  • URL shortener → key-value

Use both

And the answer interviewers like most: use both. A real e-commerce system keeps orders in Postgres, sessions and hot data in Redis, and product search in Elasticsearch. One store per job. Say that, and you've shown you design for the access pattern, not for a slogan.

In the interview

In the interview, say it like this. I'd start with Postgres, because orders need transactions and we'll query them in ways we can't predict. If chat messages grow past one machine, I'd move that table to Cassandra, partitioned by chat_id. Store, reason, and the trigger to change. That's a senior answer.

Say it like this
  • “I’d start with Postgres: orders
  • need transactions and we’ll query
  • them in ways we can’t predict.
  • If chat messages grow past one
  • machine, I’d move that table to
  • Cassandra, partitioned by chat_id.”

Interview questions

SQL or NoSQL: how do you decide?

Ask four questions: do records relate and get queried together (joins)? Do you need all-or-nothing updates across records (transactions)? Will the queries change (ad-hoc)? Is write volume beyond one machine, or is the data naturally nested? Yes to the first three points to SQL; a known access pattern with huge writes or nested shape points to NoSQL. When unsure, start with PostgreSQL.

What are the main NoSQL families?

Key-value (Redis, DynamoDB: one lookup by key), document (MongoDB: nested JSON records with flexible fields), wide-column (Cassandra: rows grouped by partition key and sorted, for huge time-ordered writes), and graph (Neo4j: nodes and edges for relationship queries).

Is NoSQL faster than SQL?

No. A well-indexed PostgreSQL serves tens of thousands of queries per second on one machine. A NoSQL store is fast only for the access pattern it was designed around and slow or impossible for others. Speed comes from matching the store to the access pattern, not from the category.

Why does NoSQL scale out more easily?

Every record has a partition key that decides which machine owns it, so writes for different keys go to different machines and adding machines adds capacity. Relational databases can be sharded too, but it is manual, and joins and transactions stop working across shards.

What do you give up with NoSQL?

Joins across partitions, ad-hoc queries that do not follow the key, and often strict consistency: many stores are eventually consistent by default, so a read right after a write can return the old value.

What is ACID and why does it matter here?

Atomic (all or nothing), Consistent (rules hold), Isolated (concurrent transactions do not interfere), Durable (committed data survives crashes). It is the guarantee that makes money transfers and orders safe, and the main reason such data stays in SQL.

Can you use both in one system?

Yes, and most real systems do: for example orders in PostgreSQL for transactions, sessions and hot reads in Redis, product search in Elasticsearch, and chat messages in Cassandra. One store per job, chosen by access pattern.