Skip to main content
Practical guidance for working with KV, whether through the env binding or the REST API.

Key Naming

Keys may contain a-z, A-Z, 0-9, and - _ / = . (no colons). Use / to group related keys:
user/123              # User data
session/abc           # Session data
cache/api/users       # Cached API response
flag/new-feature      # Feature flag
Grouping by prefix also lets you enumerate a subset later — list({ prefix: "user/" }) (or ?prefix=user/ over REST).

Value Serialization

KV stores values verbatim, so serialize complex values yourself (no base64 needed):
// Write
await env.MY_KV.put("user/123", JSON.stringify({ name: "Alice", age: 30 }));

// Read + parse
const user = await env.MY_KV.get<{ name: string; age: number }>("user/123", { type: "json" });

Missing Keys

get returns null for a key that doesn’t exist — handle it explicitly:
const value = await env.MY_KV.get("possibly-missing-key");
if (value === null) {
    return new Response("Not found", { status: 404 });
}

Keep Values Small

KV is built for many small values read on the request path, not for large blobs. A value is capped at 1 MiB (1,048,576 bytes) — a larger write is rejected with 413. Store big or binary objects in Cloud Storage and keep only the key or a small reference in KV.

Limits

LimitValue
Max value size1 MiB (1,048,576 bytes) — over → 413
Max key length256 characters — over → 400
Key charactersa-z A-Z 0-9 - _ / = . (no colons)
list page sizelimit 1–1000 (default 1000)

Don’t Rely on Atomicity

KV has no transactions or compare-and-swap, and concurrent writers to one key are last-write-wins. Don’t use it for counters, locks, or coordination — see Consistency.