Cloudflare KV isn’t just a key-value store; it’s a globally distributed database that pushes your data to the edge, right alongside your Workers.
Let’s see it in action. Imagine you have a simple Worker that needs to fetch a user’s preference, say their chosen theme for your website.
// workers/my-worker.js
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
const userId = url.searchParams.get('userId');
if (!userId) {
return new Response('User ID is required', { status: 400 });
}
const userPreferences = await MY_KV_NAMESPACE.get(userId);
if (userPreferences === null) {
return new Response('User preferences not found', { status: 404 });
}
return new Response(userPreferences, {
headers: { 'content-type': 'application/json' }
});
}
To make this work, you first create a KV namespace in your Cloudflare dashboard, let’s call it MY_KV_NAMESPACE. Then, you bind this namespace to your Worker. In your wrangler.toml file, it looks like this:
# wrangler.toml
name = "my-app"
main = "workers/my-worker.js"
[vars]
MY_KV_NAMESPACE = "MY_KV_NAMESPACE"
Now, when a request comes in for https://your-app.workers.dev/?userId=user123, the Worker will try to retrieve the value associated with the key user123 from the MY_KV_NAMESPACE KV store. If it finds it, it returns the data; otherwise, it returns a 404.
The magic here is that MY_KV_NAMESPACE isn’t sitting in one data center. Cloudflare automatically replicates your KV data across its global network. When a request hits an edge location, the Worker running there can access the locally cached copy of the KV data. This means incredibly low latency for reads, often in the tens of milliseconds, because the data doesn’t need to travel back to a central database. Writes, however, involve a quorum of data centers and are therefore slower, typically taking a few seconds to propagate globally.
So, how do you get data into KV? You can use the Cloudflare dashboard, the API, or the wrangler CLI. For example, to put a user’s preferences, you’d run:
# In your project directory
wrangler kv:key put "user123" --binding MY_KV_NAMESPACE --path /path/to/user123.json
This command takes the content of /path/to/user123.json and stores it under the key user123 in your MY_KV_NAMESPACE. The --binding flag ensures wrangler knows which namespace to target, matching the name used in your wrangler.toml.
The core problem Cloudflare KV solves is the latency introduced by geographically distant databases. By placing data at the edge, it dramatically speeds up read operations for applications served globally. It’s ideal for configuration data, user preferences, feature flags, or any read-heavy data that doesn’t change constantly. You can also use it for write-heavy scenarios, but be mindful of the eventual consistency and write latency.
One aspect that often trips people up is how KV handles data types and updates. When you put data, KV treats it as a string. If you get data, you receive it as a string. To work with JSON, you must explicitly parse it on the Worker side. For example, to update a user’s preference:
// In your Worker, after getting existing data
const preferences = JSON.parse(userPreferences || '{}'); // Handle null gracefully
preferences.theme = 'dark'; // Update the value
await MY_KV_NAMESPACE.put(userId, JSON.stringify(preferences));
This pattern of get, parse, modify, stringify, and put is fundamental when dealing with structured data in KV. You’re not directly modifying a JSON object in place; you’re replacing the entire string value associated with the key.
Understanding the eventual consistency model is crucial. While reads from a nearby edge location are fast, a write might take a few seconds to be visible everywhere. This means if a user updates a setting and immediately tries to read it back from a different edge location, they might still see the old value.
The next step is exploring Workers KV’s more advanced features, like namespaces with different replication policies or integrating with other Cloudflare services.