“NoSQL” isn’t one thing — it’s four distinct data models, each trading the relational model’s rigid schema and joins for a different scaling and access pattern. Picking the right one is a data-modeling decision driven by how you query, not a popularity contest. The four families are document, key-value, wide-column, and graph. They share themes (horizontal scaling, flexible schema, usually eventual consistency under the CAP lens) but differ sharply in what they’re good at. This page compares them; for the general “why NoSQL” framing see NoSQL.

Beyond these four data models, specialized engines exist — search engines (Elasticsearch/OpenSearch, built on an inverted index) and time-series stores (InfluxDB, Prometheus, TimescaleDB) — but these are purpose-built or layered on the families above rather than a fifth model.

The Four Families

Document

Stores self-contained documents (JSON/BSON), each a nested tree of fields. The document is the unit of read/write, so related data that’s read together lives together (no joins). Schema is per-document and flexible.

  • Examples: MongoDB, Couchbase, Azure Cosmos DB (SQL API).
  • Best for: content/catalogs, user profiles, anything with a natural aggregate boundary and evolving schema.
  • Model rule: embed what you read together; reference what you’d otherwise duplicate heavily.
{ "_id": "u42", "name": "Ada", "addresses": [ { "city": "London", "primary": true } ],
  "orders": [ { "id": "o1", "total": 99.50 } ] }

Key-Value

The simplest model: a giant distributed hash map of key → opaque value. O(1) get/put by key, no querying inside the value. Often in-memory.

  • Examples: Redis, DynamoDB (core), Memcached, etcd.
  • Best for: caching (Caching), sessions, feature flags, rate-limit counters, leaderboards.
  • Constraint: you can only fetch by key — design the key (and any secondary-index tables) around your access patterns up front.

Wide-Column

Rows are identified by a partition key and hold a flexible, sparse set of columns; data is physically grouped by partition. Built for massive write throughput and queries along a known partition + clustering key. That write throughput comes from the storage engine underneath: these stores are backed by an LSM-Tree / SSTable engine, which turns random writes into sequential appends.

  • Examples: Cassandra, ScyllaDB, HBase, Bigtable.
  • Best for: time-series, event logs, IoT/sensor data, high-write feeds at petabyte scale.
  • Model rule: query-first design — you model one table per query, denormalizing aggressively, because there are no joins and cross-partition scans are expensive (echoes sharding’s shard-key discipline).

Discord’s message store shows the rule under real load. Messages are read by channel and time, so the storage key must keep that access path local instead of scattering one channel across the cluster. Discord moved from Cassandra to ScyllaDB after operational pain around hot partitions, garbage collection, and repairs; the lesson is not that one wide-column engine always wins, but that partition shape and node behavior dominate at trillions of rows.

Graph

Stores nodes and edges as first-class citizens, making relationship traversal cheap. A query like “friends-of-friends who like X” is a local walk, not an exploding chain of joins.

  • Examples: Neo4j, Amazon Neptune, JanusGraph.
  • Best for: social networks, recommendations, fraud rings, knowledge graphs, network/IT topology.
  • Why not SQL: a deep or unpredictable traversal in a relational database requires repeated joins, index probes, and intermediate rows. A graph engine can keep adjacency relationships close to the node being expanded, reducing lookup and materialization work when the walk is selective. Both still pay for the edges they visit, and SQL can win for set-based aggregates, integrity constraints, and well-indexed fixed-depth joins; the deciding factors are traversal depth, selectivity, data locality, cache state, and the available indexes.

Comparison

FamilyRead byStrengthWeak atTypical store
DocumentDocument key + secondary indexesFlexible aggregates, dev velocityCross-document joins, multi-doc transactionsMongoDB
Key-ValueKey onlyRaw speed, simplicityQuerying value contentsRedis, DynamoDB
Wide-ColumnPartition + clustering keyWrite throughput at scaleAd-hoc queries, cross-partition joinsCassandra
GraphTraversal from a nodeDeep relationship queriesBulk aggregate scansNeo4j

Time-Series Workloads

A time-series workload is append-heavy and reads ordered ranges by series and time. The important boundary is not “contains timestamps”; it is whether cardinality, compression, retention, and time-window aggregation have become the dominant storage costs. Time-Series Databases owns the series model, partitioning, rollups, late data, and the workload-selector diagram.

Pitfalls

  • “Schemaless” means schema-on-read, not no schema. The schema moves from the database to your application code. Without discipline (and ideally validation), document collections drift into inconsistent shapes that every reader must defensively handle.
  • Modeling NoSQL like SQL. Normalizing a document store or expecting joins defeats the point and performs badly. NoSQL is query-driven: design the data around the reads you’ll do, accepting denormalization and duplication.
  • Assuming strong consistency. Most of these default to eventual consistency for availability/latency (see PACELC). Read-your-writes and cross-document atomicity often require explicit opt-in (tunable consistency, transactions) or aren’t available at all.
  • Hot partitions. Wide-column and key-value stores spread load by partition key; a poorly chosen key concentrates traffic on one node — the same hot-key problem as Sharding.
  • NoSQL ≠ “no SQL needed.” Most real systems are polyglot: a relational store as the system of record plus a key-value cache and maybe a search/graph store — not one database for everything.

Tradeoffs

Relational vs NoSQL (when to leave SQL): stay relational when you need ad-hoc queries, multi-row ACID transactions, and strong consistency over moderate data. Reach for a NoSQL family when a specific access pattern (huge write volume, deep traversals, simple key lookups at massive scale, or rapidly-evolving documents) outgrows what a single relational node serves well — and only after exhausting Replication and caching.

NewSQL (CockroachDB, Spanner, Vitess) is the third option: relational semantics and SQL with horizontal scaling — worth considering before giving up ACID for scale.

Questions

References