Workers KV for Global Config: Designing Around Eventual Consistency
Workers KV is not a strongly consistent database. Learn how to use it for global edge configuration, understand propagation delays, and avoid common pitfalls.
23 Aug 2025, 02:33 UTC

The "instant" global update that isn't
You push a configuration change to Cloudflare Workers KV expecting every edge location to serve the new value immediately. A user in Frankfurt gets the updated flag, but a user in São Paulo still sees the old one. Nothing is broken—KV is working as designed—but if your mental model treats it like a traditional database, your app will behave unpredictably.
The useful takeaway: Workers KV is a globally replicated, read-optimized cache, not a strongly consistent store. Design your application to tolerate stale reads, and KV becomes an excellent tool for edge configuration.
What KV actually promises
Workers KV is an eventually consistent key-value store. When you write a value, Cloudflare propagates it across its global network, but that propagation is not instantaneous. The platform documentation describes propagation windows that can take up to roughly 60 seconds, though the exact delay depends on network conditions and location. Treat that figure as an upper bound, not a service-level guarantee.
Reads, by contrast, are optimized for speed. KV caches values at the edge, so a get from a Worker is typically fast and does not require a round-trip to a central database. This makes KV ideal for high-read, low-write workloads: feature flags, A/B test configurations, static lookup tables, or redirect rules.
The trade-off is that you lose the ability to perform real-time synchronization. If two clients write to the same key in different regions, the last write wins, but intermediate readers may see either value until propagation completes. Financial transactions, leader election, and real-time counters belong elsewhere.
A worked example: versioned feature flags
Because you cannot assume immediate consistency, the most reliable pattern is to version your configuration values. By embedding a timestamp or semantic version inside the value, your Worker—and your debugging process—can detect whether an edge location is serving stale data.
1. Bind the namespace
In your wrangler.toml, bind a KV namespace to the Worker. Run wrangler kv namespace create CONFIG_KV from your local terminal first if you have not already; this command requires an authenticated Cloudflare account and outputs a namespace ID. This example assumes a recent Wrangler version (v3.x or later).
name = "config-worker"
main = "src/index.ts"
compatibility_date = "2024-09-23"
[[kv_namespaces]]
binding = "CONFIG_KV"
id = "your-namespace-id-here"
2. Read and write with a version field
The Worker below exposes two endpoints: one to read the current configuration, and one to update it. The stored JSON includes a version timestamp so you can compare values across regions.
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === "/config") {
// type: "json" parses the stored string automatically
const config = await env.CONFIG_KV.get("app:flags", { type: "json" });
return Response.json(config || { error: "Config not initialized" });
}
if (url.pathname === "/update") {
const newConfig = {
version: Date.now(),
maintenanceMode: true,
message: "Scheduled maintenance in progress"
};
await env.CONFIG_KV.put("app:flags", JSON.stringify(newConfig));
return new Response("Update submitted; propagation is eventual");
}
return new Response("Not found", { status: 404 });
}
};
3. Diagnose propagation
After calling /update, immediately request /config from clients in different geographic regions. If the version fields differ, the older value is still cached at that edge. This is not an error—it is the expected behavior of an eventually consistent system.
You can also inspect the namespace directly with wrangler kv key get --binding CONFIG_KV app:flags from your local terminal. Note that this reads through Cloudflare's API and may reflect a more recent state than a specific edge cache.
To revert the change, write the previous JSON object back to app:flags. Because KV does not support transactions, the old value will reappear at each edge location gradually, just like the original update.
Where KV fits—and where it breaks
| Pattern | KV Suitability | Reason |
|---|---|---|
| Feature flags read on every request | Excellent | High-read, low-write; stale reads are acceptable for minutes |
| User session counters | Poor | Concurrent writes to the same key can be lost or delayed |
| Static asset metadata | Excellent | Immutable or rarely changing data benefits from edge caching |
| Real-time inventory or pricing | Unusable | Eventual consistency can serve outdated values to customers |
Hard limits to respect
- Write throughput: KV is designed for infrequent updates. Repeatedly writing the same key in a short window can trigger rate limiting or degrade performance.
- Value size: Large values consume isolate memory. Keep configuration payloads small; store blobs in R2 or another object store and keep only references in KV.
- No transactions: KV does not support atomic multi-key operations. If you need all-or-nothing writes, use a different datastore.
Practical verification and next steps
Before relying on KV in production, deploy a minimal Worker like the one above, issue a put, and compare get results from at least two continents. If your application logic breaks when a stale value is served, KV is the wrong tool for that specific data.
Use KV for what it is: a fast, globally distributed configuration cache. Version your values so staleness is visible, keep writes infrequent, and reach for Durable Objects or an external transactional database when you need strong consistency. Check the current Cloudflare documentation for the latest quota limits and propagation behavior before you scale.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.