Workers KV -- Read, Write and Delete Operations
In this tutorial, you'll learn about Workers KV. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Workers KV provides a complete CRUD API -- put, get, delete, and list -- that lets you read and write data from Cloudflare's global edge network with simple JavaScript calls from your Worker code.
Why KV CRUD Operations Matter
Building dynamic applications at the edge requires persistent storage that works as fast as the compute layer itself. The KV CRUD API mirrors familiar database operations but is optimized for edge distribution. Every put triggers global Replication, every get reads from the nearest node, and every delete removes data worldwide. Understanding these operations in detail lets you build Caching layers, user session stores, and configuration services that work globally. Combined with Cloudflare Workers and REST APIs, KV operations form the data persistence backbone of Serverless edge applications.
Real-world use: A URL shortener service uses KV with a short code as the key and the target URL as the value. Each redirect reads from the nearest edge node in under 5ms, while new short links propagate globally within seconds.
KV Write Operation Flow
flowchart LR
W[Worker] --> P[KV put]
P --> C[Cache at write edge]
C --> R[Replicate globally]
R --> E1[Edge 1]
R --> E2[Edge 2]
R --> E3[Edge N]
C --> G[KV get reads from cache]
W --> D[KV delete]
D --> DR[Delete propagates globally]
style P fill:#f90,color:#fff
style D fill:#f90,color:#fff
Writing Values with put
The put method stores a key-value pair. You can set expiration and metadata.
export default {
async fetch(request, env) {
const userId = 'user_42';
const session = JSON.stringify({
id: userId,
loginAt: new Date().toISOString(),
role: 'admin'
});
await env.MY_KV.put(`session:${userId}`, session, {
expirationTtl: 3600,
metadata: { source: 'login-endpoint', version: 1 }
});
return new Response(`Session stored for ${userId}`, {
headers: { 'Content-Type': 'text/plain' }
});
}
}
Expected output: The session data is stored under key session:user_42 with a 1-hour TTL. The metadata object {source: "login-endpoint", version: 1} is attached and retrievable via getWithMetadata.
Reading Values with get and getWithMetadata
Read values back individually or with their associated metadata.
export default {
async fetch(request, env) {
const key = 'session:user_42';
const value = await env.MY_KV.get(key);
const { value: valWithMeta, metadata } = await env.MY_KV.getWithMetadata(key);
return new Response(JSON.stringify({
raw: value,
withMetadata: valWithMeta,
metadata: metadata
}), {
headers: { 'Content-Type': 'application/json' }
});
}
}
Expected output: Returns the session JSON string for both raw and withMetadata, plus the metadata object previously attached. Using getWithMetadata avoids a second round trip to fetch metadata separately.
Deleting Values
Remove keys with delete. Bulk delete with a list operation.
export default {
async fetch(request, env) {
await env.MY_KV.put('temp_data', 'will be deleted soon');
const beforeDelete = await env.MY_KV.get('temp_data');
await env.MY_KV.delete('temp_data');
const afterDelete = await env.MY_KV.get('temp_data');
return new Response(JSON.stringify({
beforeDelete,
afterDelete,
exists: afterDelete !== null
}), {
headers: { 'Content-Type': 'application/json' }
});
}
}
Expected output: beforeDelete returns "will be deleted soon". afterDelete returns null because the key no longer exists. Confirms the delete operation completed.
Bulk Writes with Wrangler CLI
For large initial data loads, use wrangler kv:key bulk with a JSON file.
[
{"key": "redirects/abc", "value": "https://example.com/page1"},
{"key": "redirects/def", "value": "https://example.com/page2"},
{"key": "redirects/ghi", "value": "https://example.com/page3"}
]
wrangler kv:key bulk --namespace-id=abc123def bulk-data.json
export default {
async fetch(request, env) {
const keys = await env.MY_KV.list({ prefix: 'redirects/' });
const redirects = {};
for (const key of keys.keys) {
redirects[key.name] = await env.MY_KV.get(key.name);
}
return new Response(JSON.stringify(redirects), {
headers: { 'Content-Type': 'application/json' }
});
}
}
Expected output: All three redirect entries are preloaded. The Worker lists keys with the redirects/ prefix and returns a map of all short codes to target URLs. Bulk operations handle up to 10,000 keys per request.
Common Errors
| Error | Cause | Fix |
|---|---|---|
Key length exceeds limit |
Key longer than 512 bytes | Shorten the key or use a hash-based naming scheme |
Value size limit exceeded |
Value over 25MB | Compress data or switch to R2 for large objects |
Bulk payload too large |
JSON file over 100MB | Split into multiple bulk files of 100MB or less |
Key not found on getWithMetadata |
Key does not exist or not yet propagated | Always check for null return value before processing metadata |
Cannot delete non-existent key |
Deleting a key that never existed | Use get first to verify existence or treat delete as idempotent |
Practice Questions
- What is the difference between
getandgetWithMetadatain Workers KV? - How do you set a time-to-live when writing a KV value with
put? - What is the maximum number of keys you can write in a single bulk operation?
FAQ
Summary
Workers KV supports the full CRUD lifecycle: put to write with optional TTL and metadata, get and getWithMetadata to read, delete to remove, and list to enumerate keys. Bulk operations via the Wrangler CLI handle large-scale data loading. These primitives power production systems like Doda Browser's redirect service and Durga Antivirus Pro's signature update distribution across the global edge network. Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro -- security-first tools for the modern web.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro