Database Deep Dive · 2 of 2

NoSQL — Beyond Relational

A family of databases that gave up some SQL guarantees to win something else: horizontal scale, schema flexibility, sub-millisecond latency, or a data shape relational struggles with. Pick the right family, then design for the queries you'll actually run.

DocumentsKey-ValueWide-ColumnGraphBASECAP
← Back to Database Side
Quick Facts

At a Glance

Basic Concepts

  • Schema-on-read: the store accepts whatever shape you write; the app makes sense of it on the way out.
  • BASE: Basically Available, Soft state, Eventual consistency — the trade most NoSQL stores make for scale.
  • CAP theorem: in a partition, choose Consistency or Availability. You can't have both. PACELC adds: even when there's no partition, you trade Latency vs Consistency.
  • Partition key: the field that decides which node owns a row. Pick it wrong, you get hot shards forever.
  • Denormalization is the design. No joins means duplicating data on purpose, shaped to the query.
The Four Families

Pick the Right Shape First

Document

JSON-like records keyed by ID. Nested structures, flexible fields. MongoDB, Couchbase, Firestore, DynamoDB (single-table).

Key-Value

Just get(key) / set(key, value). Blazing fast. Redis, Memcached, DynamoDB, etcd.

Wide-Column

Rows with sparse, dynamic columns; sorted by clustering key within a partition. Cassandra, ScyllaDB, HBase, Bigtable.

Graph

Nodes and edges as first-class citizens. Traversals over relationships. Neo4j, Neptune, ArangoDB, TigerGraph.

Adjacent stores worth knowing: Search (Elasticsearch, OpenSearch) for full-text and log analytics; Time-series (InfluxDB, TimescaleDB) for metrics; Vector (Pinecone, Weaviate, pgvector) for embeddings & RAG.

When to Reach for It

What NoSQL Wins At

Massive Write Throughput

Cassandra and Bigtable are built around write-optimized log-structured merge trees. Tens of thousands of writes per second per node, linearly scalable. Use them for telemetry, event logs, IoT — anything that ingests faster than a single relational primary can handle.

Predictable Single-Key Lookups at Any Scale

DynamoDB and Redis answer "given this key, give me the value" in single-digit milliseconds at any size. Sessions, shopping carts, feature flags, user profiles by ID. The trade: queries that aren't keyed by the partition key get slow or expensive (or impossible).

Genuinely Variable Shapes

Product catalogs across categories, third-party API payloads, CMS content. When fields differ per record and you don't want a hundred nullable columns, document stores fit. (But Postgres JSONB does too — only reach for a document DB when you also need its scaling model.)

Deeply Connected Data

"Friends of friends who liked the same artist." In SQL, that's a chain of joins that gets exponential. Graph databases store relationships as edges and traverse them in constant time per hop. Fraud detection, recommendation engines, identity graphs, knowledge bases.

Full-Text Search

Elasticsearch / OpenSearch invert documents into token indexes for relevance-scored search, faceting, and aggregations across billions of records. Postgres full-text gets you surprisingly far; reach for a dedicated search store when ranking quality, scale, or analytics outgrow it.

Design

Modeling Without Joins

Query-First Modeling

Relational: model the entities, then write any query. NoSQL: list every query first, then design tables/items so each query hits one partition. If a new query type appears, you may need a new table populated by a stream — that's the cost of denormalization.

Single-Table Design (DynamoDB)

Put multiple entity types in one table, distinguished by partition key prefix. Composite sort keys (USER#42, ORDER#2026-04-27#…) make hierarchical queries ("all orders for user 42 in April") a single key range scan. Powerful and unintuitive — read Alex DeBrie before you design.

Partition Keys & Hot Shards

The partition key decides which node owns the data. Choose it for even distribution. user_id with one whale customer = one node on fire while the rest idle. Bucket / salt high-cardinality writes; pre-split when you know the distribution.

Secondary Indexes Are Different Here

In Cassandra, local secondary indexes are usually a trap — they fan out across the cluster. Prefer building a second table keyed by the alternate access path and writing to both. DynamoDB's GSIs are essentially exactly that, managed for you (and billed accordingly).

Consistency

What "Eventually" Costs You

Eventual vs Strong

Most NoSQL stores default to eventual consistency on reads — you may briefly see stale data after a write. Many offer a strongly consistent read mode that costs more (DynamoDB doubles RCUs; Cassandra raises the consistency level, hurting availability and latency). Reach for it on read-after-write paths; tolerate eventual for everything else.

Transactions, Sometimes

MongoDB has multi-document ACID transactions (4.0+). DynamoDB has TransactWriteItems across up to 100 items in one region. Cassandra has lightweight transactions via Paxos — slow, use sparingly. None of these are free; design so you rarely need them, and isolate hot money-paths in a relational DB if you do.

Idempotency & Conflict Resolution

Eventual consistency means writes can land out of order or be retried. Make writes idempotent (deterministic key, upsert semantics). For concurrent updates, use last-writer-wins with a logical clock, conditional writes (IF version = N), or CRDTs for true merge.

Operations

Running NoSQL

  • Capacity is a real budget. DynamoDB charges per RCU/WCU; Cassandra cares about per-partition size (≤ 100MB rule of thumb). Capacity planning matters more here than in SQL.
  • Backups differ by family. Managed services (DynamoDB PITR, Firestore export) are easy. Self-hosted Cassandra needs careful snapshot + commit-log strategy across all nodes.
  • Schema migrations are app-side. No ALTER TABLE. Plan for old shapes coexisting with new — versioned documents, dual-read, lazy upgrade on write.
  • Observability: watch hot partitions, throttling, replication lag, GC pauses. The failure modes are different from SQL.
Pitfalls

Common Mistakes

  • Choosing NoSQL because schemas are "annoying." The schema doesn't go away — it just moves into the application code, where it's enforced inconsistently.
  • Treating Mongo like Postgres. Embedding nothing, joining everywhere with $lookup. If your query pattern is relational, use a relational DB.
  • Querying by anything but the partition key. Full table scans on a key-value or wide-column store don't scale and surprise the bill.
  • Hot partitions. One celebrity user, one viral product, one sequential timestamp key — all classic ways to overload a single shard.
  • Reaching for graph databases for shallow relationships. Two joins in Postgres beat a graph DB for most "user → posts → comments" patterns.
  • Forgetting reporting. Analytics on operational NoSQL is painful. Pipe to a warehouse (BigQuery, Snowflake, Redshift) early.
Continue

The Other Side