Reference guide · cloudflare · Published 2026-08-15 · 3 min read
Cloudflare Workers KV basics
Set up Cloudflare Workers KV. Learn the read/write limits, value size, cacheTTL, and when KV fits better than D1 for a Worker.
- ·What KV stores
- ·Free-plan limits
- ·Design for reads
What Workers KV is
Cloudflare Workers KV is a global key-value store that spreads copies of your data to the edge so a Worker can read it with very low latency from wherever a request arrives. You write to a namespace, and reads are served from the closest location, which makes it the natural companion for a Worker that needs a config value, an A/B flag, an uploaded asset, or a cached rich payload without waiting on an origin round trip.
It is eventually consistent, not strongly consistent. A write is not immediately visible everywhere; a read can briefly return the previous value until the new one propagates. For a cache or a lookup this is usually fine. For data where a client must immediately read back what it just wrote, KV is the wrong tool.
Free-plan limits
The Workers Free plan includes a bounded amount of KV usage, and every limit resets daily at 00:00 UTC. When a limit is exceeded, further operations of that type fail with an error.
| Operation | Free plan | Paid plan |
|---|---|---|
| Keys read | 100,000 per day | 10 million per month, then $0.50 per million |
| Keys written | 1,000 per day | 1 million per month, then $5.00 per million |
| Keys deleted | 1,000 per day | 1 million per month, then $5.00 per million |
| Storage | 1 GB | 1 GB, then $0.50 per GB per month |
| Value size | 25 MiB | 25 MiB |
Bulk reads are billed by the number of keys read. The constraints that matter for design are the 100,000 daily read cap on the free tier and the 25 MiB ceiling per value, not the total keys, which are unlimited per namespace.
Namespaces and keys
A namespace is a named container. You bind it to a Worker in its configuration, then access it with env.NAMESPACE. Keys are plain strings up to 512 bytes; values can be bulk data up to 25 MiB. A common pattern is to key by a stable identifier and store a JSON or serialized payload:
const cached = await env.CONFIG.get("settings", { type: "json" });
if (cached) return cached;
const fresh = await buildConfig();
await env.CONFIG.put("settings", JSON.stringify(fresh), { expirationTtl: 300 });
return fresh;
Set expirationTtl (in seconds) or expiration (a timestamp) when the value should self-expire. The minimum cacheTtl is 30 seconds, so a freshly written value cannot be cached for less than that.
Design for reads
Since reads dominate any KV workload, shape the design around the daily limit:
- Cache values with a sane
cacheTtlandexpirationTtlso repeat requests hit the written copy instead of consuming another read. - Keep hot values as single keys rather than storing duplicate copies of the same payload under several keys.
- Bulk-read values that always change together into one key when they fit, instead of issuing many small reads per request.
- Reserve KV for infrequently-written, frequently-read data. If every request writes and immediately reads back, or you need transactional integrity, look at D1 or a transactional store instead.
Pair the store with cache behaviour on the edge, because a cache in front of KV cuts the number of edge reads dramatically. The read-heavy pattern is exactly what KV is optimised for, so get the TTLs right and the free tier stretches further.