KV guide
Sessions, counters and flags in KV with void/kv — works on Outer today.
Verdict: works. KV is a standard binding for small state — sessions, counters, rate flags. Anything relational belongs in D1.
1. Declare it
In void.config.ts, under cloudflare. Edits need bun run build —
bindings are read from the built config:
cloudflare: {
kv_namespaces: [{ binding: "KV", id: "sessions" }],
},
2. Use it
import { kv } from "void/kv";
await kv.put("user:123", { name: "Alice" }, { ttl: 3600 });
const user = await kv.get<User>("user:123"); // JSON-parsed; invalid JSON → raw string
await kv.delete("user:123");
await kv.list({ prefix: "user:", limit: 100, cursor });
// Typed map with an automatic prefix
const sessions = kv.map<Session>("sessions");
Reads reach the cell that owns the namespace, so they never return a stale value — but writes to one namespace run one at a time, so a write-hot value like a busy counter belongs in a Durable Object. Never store the only copy of anything you can’t rebuild, and never secrets (use secret storage instead).
3. Deploy
kv_namespaces is an accepted deploy key
(crates/outer/src/deploy/pipeline.rs), so the namespace deploys on every
account — plan gating for bindings arrives with billing. celld creates the
namespace on first use; a typo opens a silent empty namespace, so
double-check the id.
Sources
- Void KV guide: https://void.cloud/guide/kv
- celld KV: https://celld.dev/docs/services/kv