Key-Value Storage
Void provides a typed KV client with automatic JSON serialization for Cloudflare Workers KV. Import kv from void/kv and start reading and writing data.
Basic Operations
Get
import { kv } from 'void/kv';
const user = await kv.get<User>('user:123');
// User | nullValues are automatically parsed as JSON. If the stored value isn't valid JSON, the raw string is returned.
Put
await kv.put('user:123', { name: 'Alice', role: 'admin' });Objects are automatically JSON-stringified. Strings are stored as-is.
Add a TTL (in seconds) or absolute expiration (Unix timestamp):
await kv.put('session:abc', sessionData, { ttl: 3600 });
await kv.put('token:xyz', tokenData, { expiration: 1700000000 });Attach metadata to a key:
await kv.put('user:123', userData, {
metadata: { updatedBy: 'admin' },
});Delete
await kv.delete('user:123');List
const result = await kv.list({ prefix: 'user:' });
// { keys: [{ name: "user:1" }, { name: "user:2" }], list_complete: true }Paginate with limit and cursor:
const page = await kv.list({ prefix: 'user:', limit: 100 });
if (!page.list_complete) {
const next = await kv.list({ prefix: 'user:', limit: 100, cursor: page.cursor });
}Get with Metadata
const result = await kv.getWithMetadata<User, { updatedBy: string }>('user:123');
// { value: User | null, metadata: { updatedBy: string } | null }Typed Maps
For collections of the same type, use kv.map() to create a scoped, typed client with automatic key prefixing:
const sessions = kv.map<Session>('sessions');
await sessions.put('abc', { userId: 1, token: '...' }, { ttl: 3600 });
// KV key: "sessions:abc"
const session = await sessions.get('abc');
// Session | null
await sessions.delete('abc');The map automatically prefixes all keys with "sessions:" and strips the prefix when listing:
const result = await sessions.list();
// keys: [{ name: "abc" }, { name: "def" }] (prefix stripped)Maps have the same methods as the base client (get, put, delete, list, getWithMetadata) but with a typed value and automatic prefixing.
How It Works
The KV client is a thin wrapper over the Cloudflare KV API that adds two things:
Auto serialization:
put()callsJSON.stringify()on non-string values.get()callsJSON.parse()with a fallback to the raw string for values that are not JSON. You can store and retrieve objects without manual serialization.Typed maps:
kv.map<T>(prefix)returns a scoped client where all keys are prefixed with"prefix:"and values are typed asT. This is useful for organizing related data such as sessions, cache entries, and feature flags without manually managing prefixes.
Escape hatch: The
kvclient covers the most common KV operations. For advanced use cases likegetWithMetadatawith specific cache behaviors, you can access the rawKVNamespacebinding viac.env.KVin a route handler.