Storage bindings

Cache read-heavy data in KV

Use KV for read-heavy derived values while respecting eventual consistency and keeping D1 as the authoritative record.

8 minute lesson

~~~

Workers KV distributes values for fast reads, but changes may take time to become visible everywhere.

That consistency model fits cache entries and configuration better than rapidly updated counters or unique constraints. Cache the public recent-links response with an expiration and invalidate it after writes, while accepting that a reader may briefly see the previous value.

const cached = await env.CACHE.get('recent-links', 'json')
if (cached) return Response.json(cached)
const links = await listRecentLinks(env.DB)
await env.CACHE.put('recent-links', JSON.stringify(links), { expirationTtl: 60 })

KV can return a previously cached value after a write, including a cached “not found.” Deleting or overwriting a key is therefore best-effort invalidation, not immediate global coordination. Keep D1 authoritative and make correctness independent of seeing the newest KV value.

Version cache keys when the response shape changes, for example recent-links:v2, so old data cannot be decoded as a new format. Choose the TTL from the acceptable staleness window, not from a desire for a high hit rate. If many misses can arrive together, cap the database work or add coordination; a cache miss storm can otherwise move the load rather than remove it.

Add the cache and log safe hit-or-miss metadata during local testing.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →