---
title: SQL vs NoSQL and when to use
description: How to pick between a relational database and a NoSQL one, the trade-offs, and worked examples for each.
tags: [databases, sql, nosql, architecture]
---

Use **SQL** when relationships and consistency matter. Use **NoSQL** when
flexibility and scale matter. Neither is a default; the right one usually falls
out of the problem once you look at it.

A SQL database is relational: data lives in tables of rows and columns, every row
shares the same columns, and tables link through keys. NoSQL is the umbrella for
everything else, where records don't have to share a shape and the store is
usually built to spread across many machines.

## At a glance

| SQL               | NoSQL                                        |
| ----------------- | -------------------------------------------- |
| Fixed schema      | Flexible schema                              |
| Tables            | Documents, key-value, graph, column          |
| ACID transactions | Usually eventual consistency (depends on DB) |
| Complex joins     | No joins (or limited)                        |
| Structured data   | Semi-structured / unstructured data          |

## Reach for SQL when

* The data has a stable shape and clear relationships.
* You need real transactions, where a group of writes all succeed or all fail
  together. Money, orders, and inventory live here.
* Queries get involved: joins, aggregations, questions you didn't plan for.
* Integrity matters enough to enforce it in the database, with foreign keys and
  constraints.

Usual picks: Postgres, MySQL.

## Reach for NoSQL when

* The schema changes often, or you don't fully know it yet.
* You need to scale writes across many machines, or handle high throughput.
* The access pattern is simple: look something up by its key and hand it back.
* You'd rather store data pre-shaped for reads than normalize and join later.

NoSQL isn't one thing, though. The four families solve different problems.

| Family      | Examples           | Good for                                                      |
| ----------- | ------------------ | ------------------------------------------------------------- |
| Document    | MongoDB, Firestore | Nested, flexible records like user profiles or CMS content    |
| Key-value   | Redis, DynamoDB    | Cache, sessions, counters: fast lookups by key                |
| Wide-column | Cassandra          | Time-series and huge write volume like logs or IoT data       |
| Graph       | Neo4j              | Relationship-first data like social graphs or recommendations |

## Examples

### SQL: a bank transfer

Two accounts, one moves money to the other. Both updates happen or neither does.

```sql
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
```

If the second update fails, the transaction rolls back and no money vanishes.
That all-or-nothing guarantee is the thing most NoSQL stores give up. Its formal
name is ACID; see [ACID transactions](/docs/engineering/databases/acid).

### SQL: an e-commerce order

Users place orders, orders contain items, items point at products.

```text
users >- orders >- order_items -< products
```

"Every order this user placed, with product names" is one query with a couple of
joins. The relationships are the point, and SQL models them directly.

### NoSQL document: a product catalog

Different products carry different attributes, so a rigid column layout fights
you.

```json
// a shoe
{ "id": "1", "name": "Nike Pegasus", "size": 42, "color": "red" }

// a laptop, same collection, different fields
{ "id": "2", "name": "MacBook Air", "ram": "16GB", "cpu": "M3" }
```

Each document brings its own shape. In SQL you'd add a column per attribute and
drown in nulls, or push it into a JSON blob and lose the point of columns.

### NoSQL key-value: a session cache

A session needs to come back in well under a millisecond, and there's nothing
relational about it.

```text
SET session:abc123 "{ userId: 5, cart: [...] }" EX 3600
GET session:abc123
```

Redis stores it by key, expires it after an hour, hands it back instantly. No
schema, no joins, nothing to model.

### NoSQL wide-column: sensor data

A fleet of IoT devices writes a million points a second. Cassandra spreads those
writes across nodes and keeps up; a single Postgres box would fall over. When
write volume is the whole problem, this is the shape that survives it.

## Most systems mix both

Picking "SQL vs NoSQL" is usually picking what each piece of the system is best
at.

```text
                 App
                  │
        ┌─────────┴─────────┐
    Postgres            MongoDB / Redis
    - Users             - Logs
    - Orders            - Analytics
    - Payments          - Chat, sessions
```

* **Amazon**: SQL for orders, NoSQL for sessions and caching.
* **Uber**: SQL for payments, NoSQL for trip and location data.
* **Netflix**: SQL for billing, NoSQL for recommendations and viewing history.

## Decision table

| Scenario                   | Best choice |
| -------------------------- | ----------- |
| Banking, payments, billing | SQL         |
| Inventory + orders         | SQL         |
| User authentication        | SQL         |
| Chat app                   | NoSQL       |
| Analytics, logs, IoT       | NoSQL       |
| Product catalog            | NoSQL       |
| Social feed                | NoSQL       |

## A rule of thumb

If you need relations, transactions, and enforced integrity, that's SQL. If you
need scale, a loose schema, and plain lookups by key, that's NoSQL. When you
genuinely can't tell, start with Postgres. It also stores JSON with `jsonb`, so
it stretches further than people expect, and you can add a NoSQL store later once
a specific pain shows up.
