SQL vs NoSQL
Status: đźź© COMPLETE Last updated: 2026-06-19 Plain-English tagline: The two main families of databases. SQL = strict tables, joins, SQL queries, ACID. NoSQL = flexible structures (documents, key-value, etc.) for specific needs. In 2026, start with SQL.
In plain English
When people say “the database,” they usually mean either a SQL database or a NoSQL database. The difference shapes everything else.
SQL (relational)
- Data organized in tables of rows and columns, with strict schemas
- Tables reference each other via foreign keys
- Queried with SQL (Structured Query Language) — a declarative language that’s been standard since the 1970s
- Strong consistency guarantees (ACID)
- Mature; battle-tested in every industry
Examples: Postgres, MySQL, SQLite, SQL Server, Oracle, MariaDB.
NoSQL (everything else)
A category, not a single thing. Several sub-families:
- Document stores (MongoDB, Firestore, CouchDB) — JSON-like documents, flexible schema per record
- Key-value stores (Redis, DynamoDB, etcd) — extremely simple lookups by key, very fast
- Wide-column stores (Cassandra, ScyllaDB, HBase) — designed for massive scale; complex
- Graph databases (Neo4j, Memgraph, Neptune) — optimized for relationship-heavy data
- Time-series databases (InfluxDB, TimescaleDB) — optimized for sequential data with timestamps
- Search databases (Elasticsearch, OpenSearch, Meilisearch) — optimized for full-text search
“NoSQL” originally meant “no SQL” (rejecting SQL); the modern usage is more “not only SQL” — many NoSQL DBs now have SQL-like query languages too.
Why it matters
- The choice ripples through everything. Schema design, queries, scaling, tooling, debugging — all shaped by this.
- SQL is the safe default in 2026. “Just use Postgres” is right for almost every webapp.
- NoSQL has specific strong-fit use cases worth knowing about — but they’re niches, not the rule.
- Mixed setups are common at scale: SQL for primary data + Redis for caching + Elasticsearch for search.
The classical reasons people picked NoSQL (and why most don’t hold up anymore)
In the 2010s, NoSQL was hyped as “the future” — scaling, flexibility, web-scale. Reality landed differently:
“I need to scale to billions of users”
Postgres handles way more than people assume. Stack Overflow runs on a few SQL servers. Many Series-C startups never need to leave a single Postgres instance.
”My schema is too flexible for SQL”
Postgres has JSON columns. You can mix structured + unstructured. Often the “flexibility” need was actually “I don’t know my schema yet” — and discovering the schema during MVP is normal.
”MongoDB is faster”
For some specific access patterns, yes. For most workloads, Postgres is comparable or faster, especially with proper indexes.
”Relational joins are slow”
Postgres joins on indexed columns are fast. Slow joins usually mean missing indexes or bad schema, not “SQL is slow."
"I need horizontal scaling”
Postgres has logical replication, partitioning, sharding (via Citus). For 99% of webapps, vertical scaling (bigger server) is sufficient and simpler.
The result of all this: the industry has largely returned to “Postgres for primary data, NoSQL when there’s a specific reason.”
When NoSQL is actually the right choice
Document stores (e.g. MongoDB, Firestore)
Good fit when:
- Schema genuinely varies per record (rare in practice)
- You want offline-first sync with conflict resolution (Firestore’s strength)
- Building on Firebase ecosystem
- Document-shaped queries dominate
Key-value stores (e.g. Redis)
Good fit when:
- Caching frequently-read data
- Rate limiting / counters
- Session storage
- Pub/sub messaging
- Leaderboards (Redis sorted sets)
Redis as cache is extremely common. Even projects using Postgres as primary often use Redis for the speed boost.
Graph databases (e.g. Neo4j)
Good fit when:
- Data is fundamentally a network (social graph, recommendation, fraud detection)
- Queries like “friends of friends” are common
- Path-finding is core to your product
Postgres can do graph queries (recursive CTEs) but for graph-heavy products, dedicated DBs are much better.
Time-series databases (e.g. TimescaleDB)
Good fit when:
- Huge volumes of timestamped data (metrics, sensors, logs)
- Time-based queries dominate
- Need automatic data retention / downsampling
TimescaleDB is built on Postgres so you get both worlds.
Search engines (e.g. Elasticsearch, Meilisearch)
Good fit when:
- Full-text search is core to UX
- Need relevance ranking, fuzzy matching, autocomplete, facets
Postgres has full-text search; it’s “good enough” for many cases. Dedicated search engines shine when search is the primary UX.
Schema flexibility — the headline NoSQL pitch
The single biggest “but NoSQL” argument is schema flexibility. Let’s untangle it.
NoSQL document stores allow per-record variation
// MongoDB
db.users.insertOne({ name: "George", age: 99 });
db.users.insertOne({ name: "Sarah", email: "sarah@example.com" }); // different fields, no errorPostgres JSON columns do the same thing
CREATE TABLE users (
id uuid PRIMARY KEY,
data jsonb
);
INSERT INTO users (data) VALUES ('{"name": "George", "age": 99}');
INSERT INTO users (data) VALUES ('{"name": "Sarah", "email": "sarah@example.com"}');
-- Query JSON like:
SELECT * FROM users WHERE data->>'name' = 'George';
SELECT * FROM users WHERE (data->>'age')::int > 50;You get both strict columns for known fields AND flexible JSON for variable fields, in the same row. Best of both worlds.
For new projects, that hybrid is often the right answer: structured columns for known data, JSONB for flexible bits.
A side-by-side comparison
| Aspect | SQL (Postgres) | NoSQL (typical) |
|---|---|---|
| Data structure | Tables with strict schemas | Varies: docs, KV, graph |
| Query language | SQL (standard, expressive) | Per-database, often less expressive |
| Joins | First-class, fast with indexes | Varies; often requires app-side joins |
| Schema changes | Migrations; can be heavy | Often trivial (just insert new shape) |
| Transactions | ACID, multi-row, multi-table | Limited; varies by DB |
| Consistency | Strong | Often eventual |
| Maturity | Decades | Younger (varies) |
| Tooling | Massive ecosystem | Per-DB |
| Cost at small scale | Free (Postgres) | Free tier varies |
| Cost at large scale | Predictable, often cheaper | Can spike (DynamoDB) |
| Learning curve | SQL itself once | Per-DB |
| Common access pattern | Multi-table queries | Lookup-by-key dominates |
A concrete example: the same data, two ways
A blog with users and posts.
SQL (Postgres)
CREATE TABLE users (id uuid PRIMARY KEY, name text, email text);
CREATE TABLE posts (
id uuid PRIMARY KEY,
author_id uuid REFERENCES users(id),
title text,
body text
);
-- Get post with author
SELECT posts.*, users.name AS author_name
FROM posts JOIN users ON users.id = posts.author_id
WHERE posts.id = '...';Document (MongoDB)
// Option A: embedded — denormalized
db.posts.insertOne({
id: "...",
title: "...",
body: "...",
author: { id: "...", name: "George", email: "..." } // embedded
});
// Option B: referenced — like SQL
db.posts.insertOne({ id: "...", author_id: "..." });
// Then app-side: db.users.findOne({ _id: post.author_id })Embedded is fast for reads but awful if the author’s name changes (must update every post). Referenced requires app-side joining (two queries).
SQL with proper joins is usually the cleaner answer for this kind of data.
”Polyglot persistence” — using multiple DBs
Many real systems use multiple databases for different jobs:
- Postgres — primary application data
- Redis — cache, sessions, rate limits
- Elasticsearch / Meilisearch — search
- TimescaleDB — metrics
- S3 / object storage — files, media
- Neo4j — recommendation engine (if you have one)
Each has its sweet spot. You don’t need them all from day one — adding them when specific needs justify is healthy.
For most solo-developer projects in 2026: Postgres (via Supabase) covers everything you need at launch. Add Redis caching later if needed.
Common gotchas
-
Choosing NoSQL because it’s “modern.” Modern doesn’t mean better-fit. Pick based on access patterns, not aesthetics.
-
Choosing SQL because it’s familiar. Sometimes a genuine fit elsewhere is missed. Be honest about the use case.
-
Underestimating Postgres. It does JSON, full-text search, geo, graph queries, time-series (with TimescaleDB), pub/sub (LISTEN/NOTIFY), and more.
-
Overestimating MongoDB’s flexibility. Real apps converge on schemas anyway; you’ll just enforce them in app code instead of DB.
-
Thinking NoSQL = no schema. Documents have implicit schemas; they’re just unchecked. You still need to think about structure.
-
Thinking SQL = inflexible. With JSON columns and proper migrations, SQL is plenty flexible.
-
DynamoDB cost surprises. Pay-per-request can be cheap or wildly expensive depending on access patterns. Model carefully.
-
MongoDB consistency surprises. Default consistency is weaker than people expect. Read the docs.
-
Not handling joins in NoSQL. “We’ll join client-side” usually means N+1 queries or denormalization headaches.
-
Sharding too early. Both SQL and NoSQL have horizontal scaling. Most projects don’t need it. Vertical scaling first.
-
Eventually consistent reads breaking UX. A user creates a record; the next read doesn’t see it. Bug or feature? Plan UI for this.
-
Cross-DB transactions. If your app needs transactionality across DBs (Postgres + Redis), it gets hairy. Saga patterns, dual writes, etc.
-
Lock-in. Many NoSQL services (DynamoDB, Firestore) are tied to specific clouds. Postgres is portable.
-
“Schemaless” databases that secretly have schemas. Your indexes, your validation rules, your application code all assume a shape. You haven’t escaped schema — just made it implicit.
-
Performance assumptions. “X is faster” without benchmarking your specific workload is folk wisdom. Measure.
-
Forgetting full-text search. Postgres’ full-text search is good for many use cases; don’t reach for Elasticsearch reflexively.
-
Using a graph database for normal data. Graph DBs shine when graphs are core. For “users have posts,” SQL is simpler.
-
Misunderstanding CAP / consistency models. Distributed DBs make trade-offs (consistency vs. availability vs. partition tolerance). For most webapps, you want consistency, which is Postgres territory.
See also
- What is a database? đźź©
- SQL — the language 🟩
- Postgres đźź©
- Supabase 🟩 🟦 — managed Postgres
- Schema design 🟥
- Row-Level Security 🟩 — Postgres-specific feature
- Transactions & ACID 🟥
- Indexes & performance 🟥
- Embeddings 🟩 — pgvector lets Postgres do vector search
- Glossary: SQL, NoSQL, Database
Sources
- Postgres vs. MongoDB benchmarks — Postgres docs
- MongoDB documentation
- Designing Data-Intensive Applications (Kleppmann) — the canonical comparison
- Use the Index, Luke! — focuses on SQL but principles transfer
- “Just use Postgres” (Hussein Nasser) — popular framing of modern consensus