After this lesson you'll be able to read and write Workers KV from a Worker, reason about its eventual-consistency window instead of getting surprised by it, and pick KV correctly (or reject it) for a given workload.
Workers KV is a key-value store replicated across Cloudflare's edge, built for workloads that are read constantly and written rarely. A value written to KV is cached close to wherever it's read, so a Worker in Tokyo and a Worker in Frankfurt can both fetch the same key with single-digit-millisecond latency — but that speed comes from a deliberate tradeoff: KV is eventually consistent, not strongly consistent. Understanding that tradeoff is most of what you need to use KV well.
KV's storage is centralized, but reads are served from a hybrid push/pull cache at the edge location closest to the request. The first read of a key at a given location pulls it from central storage and caches it there; subsequent reads at that location are served from the local cache. When you write a new value, it's usually visible immediately at the location where the write happened — but other locations that already have a cached copy keep serving their cached version until it expires, which can take up to 60 seconds or more. This applies symmetrically: deleting a key can leave other locations still returning the old value, and a location that previously got a "not found" for a key can keep returning "not found" for a while after the key is created.
This is not a bug to work around — it's the mechanism that makes KV fast. Cloudflare trades a bounded staleness window for the ability to serve reads from cache at every edge location instead of round-tripping to a single source of truth on every request. If your access pattern is read-heavy and a few seconds (occasionally up to a minute) of staleness is tolerable, this trade is free performance. If it isn't tolerable, KV is the wrong tool — see the pitfall below.
Bind a namespace in wrangler.jsonc:
{
"kv_namespaces": [
{ "binding": "CONFIG", "id": "<your-namespace-id>" }
]
}
Create the namespace once with wrangler, then read and write it through the binding:
npx wrangler kv namespace create CONFIG
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === "/flag") {
// type: "json" parses the stored string for you;
// cacheTtl tells this edge location how long it may serve
// its local cached copy before re-checking (minimum 60s).
const flags = await env.CONFIG.get("feature-flags", {
type: "json",
cacheTtl: 300,
});
return Response.json(flags ?? {});
}
if (url.pathname === "/session" && request.method === "POST") {
const { userId } = await request.json();
const token = crypto.randomUUID();
// expirationTtl is in seconds from now; KV enforces a 60s minimum.
// The key self-deletes — no cleanup job needed.
await env.CONFIG.put(`session:${token}`, JSON.stringify({ userId }), {
expirationTtl: 60 * 60 * 24, // 24 hours
});
return Response.json({ token });
}
return new Response("Not found", { status: 404 });
},
};
put(key, value, options) accepts either expirationTtl (seconds from now, minimum 60) or expiration (an absolute Unix timestamp) — use whichever reads more naturally at the call site. Values are capped at 25 MiB, keys at 512 bytes, and KV enforces roughly one write per second to the same key before returning a 429, which is another sign it's built for infrequent writes, not a hot counter.
Free plan (per day): 100,000 reads, 1,000 writes, 1,000 deletes, 1,000 list operations, 1 GB stored.
Paid plan (Workers Paid, per month, then metered overage): 10 million reads included ($0.50/million after), 1 million writes/deletes/list operations each included ($5.00/million after), 1 GB storage included ($0.50/GB-month after). Every operation counts toward billing even if it returns null or 404 — a miss still costs a read. There's no data transfer charge.
These numbers move over time — verify against the live page before quoting them to someone else: developers.cloudflare.com/kv/platform/pricing.
expirationTtl, serve subsequent requests from the edge instead of re-hitting a slow or rate-limited origin.Cloudflare Workers KV — How KV works is the authoritative explanation of the consistency model and propagation timing; pair it with the KV API reference for method signatures and KV pricing for current rates.
KV caches values at edge locations to serve reads with very low latency from wherever the request lands, rather than always routing to one source of truth. That caching is what makes writes take up to ~60 seconds to propagate everywhere — it's a deliberate tradeoff of staleness for read speed, aimed at read-heavy, write-rare workloads.
If you need every reader to see the latest write immediately, use D1 (relational, transactional) or Durable Objects (strongly consistent per-key actor state) instead of KV.