Skip to content

NoSQL Databases

The CAP theorem, formalised by Gilbert and Lynch in 2002 based on Brewer’s 2000 conjecture, states That a distributed data store can provide at most two of three guarantees:

  • Consistency (C): every read receives the most recent write or an error
  • Availability (A): every request receives a non-error response (without guarantee about which data version)
  • Partition Tolerance (P): the system continues to operate despite arbitrary message loss or delay between nodes

Network partitions are not theoretical — they happen regularly in production. A switch fails, a DNS Update propagates slowly, a garbage collector pause causes a timeout, a cross-datacenter link Degrades. Any distributed system must tolerate partitions, which means the real choice is between CP and AP:

CategoryStrategyExample Systems
CPPreserve consistency, sacrifice availability during partitionsPostgreSQL (sync replicas), HBase, Redis (with replication)
APPreserve availability, sacrifice consistency during partitionsMongoDB (default, w:1), Cassandra, DynamoDB, CouchDB, Riak

The PACELC theorem (Abadi, 2012) extends CAP: when there is no partition (the EL part), the System must choose between Latency and Consistency:

\mathrm{PA \to \mathrm{EL : \mathrm{when no partition, prefer availability and latency over consistency

\mathrm{PC \to \mathrm{EC : \mathrm{when no partition, prefer consistency, accepting higher latency

This captures a nuance that CAP misses: even during normal operation (no partition), systems make Consistency-latency trade-offs. DynamoDB defaults to eventual consistency for low latency but can be Configured for strong consistency (higher latency). Cassandra defaults to eventual consistency but Supports tunable consistency per operation.

Consistency is not binary. There is a spectrum of consistency models, from strongest to weakest:

ModelGuaranteeExamples
LinearizableOperations appear to execute atomically and in real-time orderSingle-node databases, ZooKeeper
SequentialOperations appear in some total order consistent with real timeGoogle Spanner (external consistency)
SerializableEquivalent to some serial execution of transactionsPostgreSQL SERIALIZABLE
Snapshot IsolationEach transaction reads from a consistent snapshotPostgreSQL REPEATABLE READ
CausalCausally related operations are seen by all nodes in orderDynamoDB (with consistent reads)
Read-your-writesA reader always sees its own writesMost systems with sticky sessions
SessionConsistency within a single client sessionMongoDB (read preference)
EventualIf no new writes, all reads eventually converge to the same valueCassandra, CouchDB, DynamoDB (default)

RocksDB (used by MongoDB’s WiredTiger for caching, TiKV, and many other systems) is a popular LSM Tree implementation. It is configurable: you can tune compaction strategy, bloom filter size, Compression, block cache, and write buffer size to optimise for specific workloads.

Amazon DynamoDB is a fully managed, serverless key-value and document store that implements a Dynamo-style architecture.

Data model:

{
"TableName": "Orders",
"KeySchema": [
{ "AttributeName": "customer_id", "KeyType": "HASH" },
{ "AttributeName": "order_id", "KeyType": "RANGE" }
],
"AttributeDefinitions": [
{ "AttributeName": "customer_id", "AttributeType": "S" },
{ "AttributeName": "order_id", "AttributeType": "S" }
],
"BillingMode": "PAY_PER_REQUEST"
}

Capacity modes:

ModeCharacteristics
ProvisionedSpecify read/write capacity units; cheaper for predictable workloads
On-DemandAuto-scales; pay per request; more expensive for steady workloads

Global Secondary Indexes (GSI):

  • Allows querying on non-key attributes
  • Eventually consistent by default (can be configured for strong consistency)
  • Consumes additional capacity units
  • Limited to 20 per table

DynamoDB Streams:

  • Time-ordered sequence of item-level changes (insert, modify, delete)
  • Enables event-driven architectures (trigger Lambda on change)
  • 24-hour retention by default

Elasticsearch is often used alongside a primary database for full-text search. It is a distributed, RESTful search engine built on Apache Lucene.

PUT /products/_doc/1
{
"name": "Precision Wrench Set",
"category": "Tools",
"price": 49.99,
"description": "A set of 12 precision wrenches for mechanical work",
"tags": ["automotive", "mechanical", "hand-tools"],
"in_stock": true
}
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "description": "precision wrench" } },
{ "term": { "in_stock": true } }
],
"filter": [
{ "range": { "price": { "lte": 100 } } }
]
},
"aggs": {
"by_category": {
"terms": { "field": "category" }
}
}
}
}