NoSQL#
“NoSQL” lumps together everything that isn’t a traditional relational database. Each subtype solves a different problem; treating them as one category leads to bad choices.
Document#
The aggregate-oriented variant. Whole objects live as nested JSON documents indexed by id and arbitrary fields. Mongo dominates; Couchbase, Firestore, and RavenDB occupy specific niches; Postgres with JSONB often beats them all when the workload also wants relational joins.
Self-contained JSON-shaped objects, indexed by id and arbitrary fields.
MongoDB, the dominant document store.
Couchbase, document + cache.
Firestore, managed, strong on mobile.
RavenDB, .NET-first.
PostgreSQL with JSONB, often the right “document store” if you also need joins.
Sweet spot: aggregates that fit naturally as a single document and rarely need joins; flexible schemas where most fields are optional.
Watch-outs.
Modeling many-to-many through embedded documents leads to update pain.
Ad-hoc analytics across documents is harder than across rows.
Transactions across documents exist (Mongo 4+) but cost more than the single-document case.
Key-Value#
The simplest data model that ships at scale. Redis and Valkey lead in-memory; etcd holds Kubernetes config; DynamoDB is the AWS managed pick; LMDB and RocksDB embed. Sweet spots are caches, sessions, rate limits, leaderboards, queues, and real-time presence.
The simplest model: put(key, value), get(key). Optimized for
single-key throughput.
Redis / Valkey, in-memory, with rich data types (strings, lists, hashes, sets, sorted sets, streams).
Memcached, pure cache, no persistence.
etcd, consensus-backed config store; powers Kubernetes.
DynamoDB, AWS managed; key-value with secondary indexes; serverless billing.
Sweet spot: caches, session stores, rate limiters, leaderboards (Redis sorted sets), feature flags, queues, real-time presence.
Redis Patterns#
Cache-aside, read miss → fetch from DB → set in Redis with TTL.
Rate limit,
INCR+EXPIREper key per window.Distributed locks,
SET key value NX PX 30000; release with Lua script.Streams, append-only, replayable; consumer groups.
Pub/Sub, broadcast to subscribers; no replay.
The most common mistake: treating Redis as a database. Cached data is disposable; persistent state belongs elsewhere unless the durability story has been thought through.
Wide-Column#
The Bigtable family. Cassandra and ScyllaDB write across many regions with no single primary; HBase and Bigtable pin to the Hadoop and GCP ecosystems. Sweet spot is write-heavy time series, telemetry, and event streams at scale, where joins don’t exist and modeling is per-query.
Tables of rows keyed by a partition key, with sparse columns within each row.
Cassandra, multi-region writes, no single primary, eventual consistency.
ScyllaDB, Cassandra-compatible C++ rewrite; faster.
HBase, Hadoop-ecosystem.
Bigtable, GCP managed.
Sweet spot: write-heavy time-series, IoT, telemetry, append-only event streams at very large scale, multi-DC writes.
Watch-outs.
Modeling is the skill; data is denormalized per query, not per entity.
Joins don’t exist; you precompute them at write time.
The CAP-theorem tradeoffs are real; pick a consistency level per query.
Graph#
The format where edges are first-class. Neo4j leads with Cypher; Neptune and Memgraph speak openCypher; Dgraph and JanusGraph cover their own niches. Sweet spots are recommendations, fraud detection, identity graphs, and any analysis that traverses many hops, where SQL joins suffer.
First-class edges between nodes; queries traverse the graph.
Neo4j, the dominant graph DB; Cypher query language.
Amazon Neptune, managed, Gremlin / SPARQL / openCypher.
Memgraph, in-memory, openCypher-compatible.
Dgraph, distributed, GraphQL-flavored.
JanusGraph, on top of Cassandra / Bigtable.
Sweet spot: recommendations, fraud detection, identity / access graphs, network / dependency / social analyses.
A relational database with foreign keys models a graph; the question is whether you query the graph deeply enough that traversal-native performance matters.
Time-Series#
The kind tuned for many writes per second indexed by time, with retention policies and downsampling built in. InfluxDB is the standard TSDB; Timescale layers on Postgres; Prometheus pulls metrics; VictoriaMetrics scales the Prometheus protocol; QuestDB serves SQL natively.
Optimized for many writes per second indexed by time, with downsampling and retention policies.
InfluxDB, the standard TSDB.
TimescaleDB, Postgres extension.
Prometheus, pull-model metrics; not for raw event storage.
VictoriaMetrics, Prometheus-compatible, faster.
QuestDB, SQL-native time-series.
Vector / Embedding#
The newest mainstream category. Vector databases store high-dimensional embeddings and answer approximate nearest-neighbor queries, the search layer that powers RAG for LLMs. pgvector covers most workloads under tens of millions; Qdrant, Weaviate, Milvus, Pinecone, and Chroma scale further.
pgvector, Postgres extension; often “good enough” for the first many millions of vectors.
Qdrant, Rust, open source.
Weaviate, with built-in vectorizers.
Milvus, distributed.
Pinecone, managed.
Chroma, developer-friendly local default.
Indexing structures: HNSW (most common), IVF, ScaNN. Tradeoff: recall vs. latency vs. memory.
Multi-Model#
The hybrid family. ArangoDB, OrientDB, and FoundationDB expose multiple data models through one engine, which can replace a stack of specialized stores. The risk: future requirements push the workload outside the engine’s strongest mode and the multi-model promise stops paying off.
Some databases offer multiple models behind one engine.
ArangoDB, document + graph + key-value.
OrientDB, similar.
FoundationDB, ordered key-value with layers (SQL, document, etc.).
Useful when the alternative is running multiple specialized stores; risky when a future requirement strains the engine outside its strongest mode.
Choosing a NoSQL Store#
The decision tree for picking among NoSQL families. Access pattern, consistency tolerance, scale profile, and operational reality drive the choice; one rarely beats Postgres on all four. The boring 2026 answer remains: start with Postgres; specialize only when a profile demands it.
Questions that usually drive the answer.
Access pattern, single-key get? range scan? graph traversal? full-text search? aggregation?
Consistency, can the workload tolerate eventual consistency?
Scale profile, many small reads, large analytical scans, write-heavy?
Operational reality, can your team run a Cassandra cluster?
The boring answer in 2026 still holds: start with PostgreSQL, add a specialized store only when a profile or specific feature genuinely requires it.