3.4 NoSQL stores and caching

Describes the cloud storage and database landscape as of August 2026

What this is and why it exists

Non-relational stores and caches are both answers to "the database is slow", and both go wrong in the same way: chosen for a reason nobody wrote down, and then trusted with data whose correctness depends on rules the store does not enforce. This lesson gives you a real reason to reach for each, and the two failures — hot partitions and stale caches — that account for most of the pain.

The vocabulary

  • Key-value store — you hand it a key, it hands back a value; nothing else. Amazon's DynamoDB is the common example, Azure's Cosmos DB and Google's Firestore and Bigtable cover the same ground.
  • Document store — values are structured documents you can query inside, not opaque blobs.
  • Wide-column store — rows with a shared partition key and many columns, designed for enormous tables and predictable access.
  • Partition key — the part of the key that decides which physical partition a record lives on.
  • Hot partition — one partition receiving far more traffic than the others, limiting the whole table.
  • Cache — a fast store holding copies of expensive answers. Amazon's ElastiCache, Azure Cache for Redis and Google's Memorystore are managed forms.
  • TTL — how long a cached value may be used before it must be fetched again.
  • Cache-aside — the application checks the cache, and on a miss fetches from the database and stores the result.
  • Write-through — the application writes to the cache and the database together, so the cache is never behind.

The mental model

A relational database earns its keep with joins, transactions across tables, and constraints it enforces for you. A non-relational store trades some or all of that for scale and for predictable latency at very large sizes. So the honest question is not "which is more modern" but "which of those guarantees am I willing to give up, and what do I get for it". If you cannot name what you are giving up, the relational database is the right default — and every serious non-relational store now has a use case it genuinely wins: key-value for lookups by a known identifier at enormous rates, documents for records whose shape varies, wide-column for time-series and event data where you always read by the same key.

The design decision that matters in these stores is the partition key, because it is chosen once and is very hard to change. It decides which physical partition a record lands on, and each partition has its own throughput ceiling. Choose a key with many distinct, evenly-used values and load spreads. Choose one with few values, or one where today's records all share the same value — a date, a status, a country where most of your users live — and you have a hot partition: one shard taking almost all the traffic while the table as a whole looks under-used, and adding capacity does not help because the limit is per-partition. Design for the reads you will actually do, and check the distribution of the key you plan to use before you commit to it.

Caching is a different bargain: you accept the possibility of being wrong for a while in exchange for speed. That is a fine trade when you decide how long "a while" is, and a bug when you do not. Cache-aside is the usual pattern — look in the cache, and on a miss read the database and store the result with a TTL — and it is popular because it is simple and the cache can never hold something the database never had. Write-through updates cache and database together, so reads never see stale data at the cost of slower writes and a cache full of things nobody asked for.

The hard part is invalidation, and the hard part of the hard part is being honest about it. Every cached value needs an answer to "how does this stop being wrong". A TTL is the answer that always works, because the value expires whether or not anyone remembered it exists — short TTLs for things that change and matter, long ones for things that barely change. Explicit invalidation on write is more precise and much easier to get wrong, because it needs every code path that changes the data to know about every cached form of it, and the path added six months later will not. A third rule saves grief: never cache something you are not willing to serve slightly out of date. Prices, permissions and balances are the usual regrets, and the same rule tells you what is safe — a product description, a rendered page, an expensive aggregate that is reported hourly anyway.

What you should now be able to explain or do

Say what a relational database gives you that a non-relational one may not, and name a workload where the trade is worth it. Choose a partition key for a described dataset and justify it against a bad alternative. Recognise a hot partition from its symptoms and explain why more capacity does not fix it. Implement cache-aside in words, including where the TTL goes. Give one thing safe to cache and one that is not, with reasons.

Check yourself

Which guarantee — joins, cross-table transactions, enforced constraints — you are giving up, and what you get in return. If you cannot name it, the relational database is the right default.

A hot partition. Limits apply per partition, so one heavily-used key value can be at its ceiling while the table as a whole looks quiet — and raising total capacity does not move it.

Look in the cache; on a miss, read the database, store the result with a TTL, and return it.

Because it works even when a code path forgets. Explicit invalidation requires every write path to know about every cached form of the data, and the path added later will not.

Permissions, balances or prices — anything where being briefly out of date is a real error rather than a small delay. If you are not willing to serve a value slightly stale, do not cache it.

Go deeper

These videos are on YouTube. Opening the link takes you to YouTube's page. Pressing "Watch here" loads YouTube's player into this page — nothing loads from YouTube until you do. Either way the video comes from Google and uses much more mobile data than a page of text. Something wrong with a link here?

Back to NoSQL stores and caching: work through the checklist