Loading...
Loading...
Cloudflare Workers KV global key-value storage. Use for namespaces, caching, TTL, or encountering KV_ERROR, 429 rate limits, consistency issues.
npx skill4agent add secondsky/claude-skills cloudflare-kvbunx wrangler kv namespace create MY_NAMESPACE
bunx wrangler kv namespace create MY_NAMESPACE --preview{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2025-10-11",
"kv_namespaces": [
{
"binding": "MY_NAMESPACE",
"id": "<PRODUCTION_ID>",
"preview_id": "<PREVIEW_ID>"
}
]
}export default {
async fetch(request, env, ctx) {
// Write
await env.MY_NAMESPACE.put('key', 'value');
// Read
const value = await env.MY_NAMESPACE.get('key');
// Delete
await env.MY_NAMESPACE.delete('key');
return new Response(value);
}
};references/setup-guide.md// Basic
await env.MY_NAMESPACE.put('key', 'value');
// With TTL (1 hour)
await env.MY_NAMESPACE.put('key', 'value', {
expirationTtl: 3600
});
// With expiration timestamp
await env.MY_NAMESPACE.put('key', 'value', {
expiration: Math.floor(Date.now() / 1000) + 3600
});
// With metadata
await env.MY_NAMESPACE.put('key', 'value', {
metadata: { role: 'admin', created: Date.now() }
});// Simple get
const value = await env.MY_NAMESPACE.get('key');
// With type
const text = await env.MY_NAMESPACE.get('key', 'text');
const json = await env.MY_NAMESPACE.get('key', 'json');
const buffer = await env.MY_NAMESPACE.get('key', 'arrayBuffer');
const stream = await env.MY_NAMESPACE.get('key', 'stream');
// With metadata
const { value, metadata } = await env.MY_NAMESPACE.getWithMetadata('key');await env.MY_NAMESPACE.delete('key');// Basic list
const { keys } = await env.MY_NAMESPACE.list();
// With prefix
const { keys } = await env.MY_NAMESPACE.list({
prefix: 'user:',
limit: 100
});
// Pagination
const { keys, cursor } = await env.MY_NAMESPACE.list({
cursor: previousCursor
});const cacheKey = `api:${url}`;
let cached = await env.MY_NAMESPACE.get(cacheKey, 'json');
if (!cached) {
cached = await fetch(url).then(r => r.json());
await env.MY_NAMESPACE.put(cacheKey, JSON.stringify(cached), {
expirationTtl: 300 // 5 minutes
});
}
return Response.json(cached);const userId = '123';
const preferences = {
theme: 'dark',
language: 'en'
};
await env.MY_NAMESPACE.put(
`user:${userId}:preferences`,
JSON.stringify(preferences),
{
metadata: { updated: Date.now() }
}
);const key = `ratelimit:${ip}`;
const count = parseInt(await env.MY_NAMESPACE.get(key) || '0');
if (count >= 100) {
return new Response('Rate limit exceeded', { status: 429 });
}
await env.MY_NAMESPACE.put(key, String(count + 1), {
expirationTtl: 60 // 1 minute window
});const { keys } = await env.MY_NAMESPACE.list({
prefix: 'user:',
limit: 100
});
const users = await Promise.all(
keys.map(({ name }) => env.MY_NAMESPACE.get(name, 'json'))
);export default {
async fetch(request, env, ctx) {
// Don't wait for KV write
ctx.waitUntil(
env.MY_NAMESPACE.put('analytics', JSON.stringify(data))
);
return new Response('OK');
}
};references/limits-quotas.md// Write
await env.MY_NAMESPACE.put('key', 'value');
// May not be visible immediately in other regions
const value = await env.MY_NAMESPACE.get('key'); // Might be nullreferences/setup-guide.mdreferences/best-practices.mdreferences/performance-tuning.mdreferences/workers-api.mdreferences/troubleshooting.mdreferences/limits-quotas.mdreferences/migration-guide.mdreferences/best-practices.mdsetup-guide.mdworkers-api.mdtroubleshooting.mdlimits-quotas.mdmigration-guide.mdperformance-tuning.mdtemplates/kv-basic-operations.tskv-caching-pattern.tskv-list-pagination.tskv-metadata-pattern.tswrangler-kv-config.jsoncscripts/check-versions.shtest-kv-connection.shsetup-kv-namespace.shvalidate-kv-config.shanalyze-kv-usage.sh/cloudflare-kv:setup/cloudflare-kv:test/cloudflare-kv:optimizekv-optimizerkv-debuggerexamples/rate-limiting/session-management/api-caching/config-management/references/setup-guide.md