Overview
NoSQL is a family of databases that do not use the relational table model. The main types are key-value stores (Redis, DynamoDB), document stores (MongoDB), wide-column stores (Cassandra, HBase), and graph databases (Neo4j). Most trade some query flexibility or consistency for horizontal scalability, flexible schemas, or a data model that matches a specific access pattern.
The key design rule is to model data around queries, not entities. In a relational database you normalize and join at read time; in most NoSQL databases you know your access patterns up front and store data so each query reads one partition. Good NoSQL design starts with 'what questions will the application ask?'.
A relational database is a general-purpose warehouse with shelves for everything. NoSQL databases are specialized rooms: a coat check (key-value), a filing room of self-contained folders (document), a huge ledger split across buildings (wide-column), and a map of relationships (graph). Each is excellent for its purpose.
When to use it
- Very high write throughput or massive data volume across many nodes.
- Simple, known access patterns (get by key, list by partition).
- Flexible or rapidly evolving schemas.
- Specialized models: graphs, time series, caching.
Where it shows up in interviews
Recognize it when: billions of events, messages, or sensor readings.
- Design a chat message store
- Design a metrics or IoT system
Recognize it when: get or put by ID with single-digit ms latency.
- Design a shopping cart
- Design a session store
- Design a URL shortener
Recognize it when: friends of friends, recommendations.
- Design a social graph
- Design fraud ring detection
Where it is used in real software
Backs Amazon's shopping cart lineage (the Dynamo paper) and serves trillions of requests during Prime Day with single-digit millisecond latency.
Used for huge write-heavy datasets across many data centers.
Stores trillions of messages; it moved from Cassandra to ScyllaDB for lower latency.
Key terms
- Key-value
- Get and put values by key.
- Document
- JSON-like documents with nested fields and indexes.
- Wide-column
- Rows grouped by partition key and sorted by clustering columns.
- Graph
- Nodes and edges with traversal queries.
- Partition key
- Determines which node stores the data; the most important design choice.
How it works, step by step
- 1List access patterns
Get user by ID, list messages in a channel by time, and so on.
- 2Choose the model
Key-value, document, wide-column, or graph, based on those patterns.
- 3Pick the partition key
High cardinality and even distribution; queries should hit one partition.
- 4Denormalize
Store data together in the shape each query needs; accept duplication.
- 5Plan consistency
Choose per-operation consistency levels and handle eventual consistency.
NoSQL types compared
Pick by access pattern
| Type | Examples | Best for | Weak at |
|---|---|---|---|
| Key-value | Redis, DynamoDB | Caching, sessions, carts | Queries by non-key fields |
| Document | MongoDB, Couchbase | Flexible entities, catalogs | Multi-document joins |
| Wide-column | Cassandra, ScyllaDB, Bigtable | Time series, messages, huge writes | Ad hoc queries |
| Graph | Neo4j, Neptune | Relationship traversal | Bulk analytics on everything |
NOWType: Key-value | Examples: Redis, DynamoDB | Best for: Caching, sessions, carts | Weak at: Queries by non-key fields
Many companies use several: PostgreSQL for orders, Redis for caching, Cassandra for events, and a graph for recommendations (polyglot persistence).
Implementation
-- Messages in a channel, newest first: the query drives the table designCREATE TABLE messages_by_channel ( channel_id UUID, bucket TEXT, -- e.g. '2026-09' to keep partitions bounded sent_at TIMEUUID, author_id UUID, body TEXT, PRIMARY KEY ((channel_id, bucket), sent_at)) WITH CLUSTERING ORDER BY (sent_at DESC); -- Single-partition read, very fast at any scaleSELECT author_id, body, sent_atFROM messages_by_channelWHERE channel_id = ? AND bucket = '2026-09'LIMIT 50;Complexity and performance
Single-digit ms at scale.
Data rebalances by partition.
Trade-offs
SQL answers new questions with new queries; NoSQL often needs a new table or index for each new access pattern.
Many NoSQL systems default to eventual consistency and limited transactions; check what each operation guarantees.
Variants and related techniques
InfluxDB and TimescaleDB optimize for timestamped metrics.
Elasticsearch and OpenSearch are document stores with inverted indexes for full-text search.
Distributed SQL systems that aim for NoSQL-like scale with SQL and transactions.
Common mistakes
- Modeling NoSQL like relational tables.
Fix: Design per query and denormalize.
- Low-cardinality or hot partition keys.
Fix: Use keys with many distinct values and even traffic; add buckets for heavy partitions.
- Unbounded partitions.
Fix: Bucket by time so partitions stay a manageable size.
Interview questions
Why would you choose Cassandra for chat messages?
Write-heavy, huge volume, and a simple access pattern: fetch recent messages in a channel. Partitioning by channel and bucket with messages sorted by time makes each read a single-partition scan, and it scales linearly by adding nodes.
What is denormalization in NoSQL and why is it acceptable?
Storing the same data in several places shaped for different queries. It trades storage and write complexity for fast single-partition reads, which is usually the bottleneck at scale.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Choose a database type for 5 features of a social app | Easy | Model selection. |
| Design a DynamoDB table for an e-commerce cart | Medium | Keys from access patterns. |
| Design message storage for Discord | Hard | Partitioning and buckets. |