Skip to content
Built with

Key-value storage ​

Build & Deploy

Read and write data in Cloudflare Workers KV with kv from void/kv. Values are stored as JSON, and kv.map() gives a collection its own key prefix and value type.

On this pageGet, put, delete and list keys · Store typed collections with kv.map() · Read metadata

Basic operations ​

These examples read, write, delete and list keys.

Get ​

ts
import { kv } from 'void/kv';

const user = await kv.get<User>('user:123');
// User | null

Values are parsed as JSON. If a value is not valid JSON, you get the raw string.

Put ​

ts
await kv.put('user:123', { name: 'Alice', role: 'admin' });

All values are stored as JSON, strings included. Reads keep the type, so "123" or "null" comes back as a string.

This step sets a TTL in seconds, or an absolute expiry as a Unix timestamp.

ts
await kv.put('session:abc', sessionData, { ttl: 3600 });
await kv.put('token:xyz', tokenData, { expiration: 1700000000 });

This step attaches metadata to a key.

ts
await kv.put('user:123', userData, {
  metadata: { updatedBy: 'admin' },
});

Delete ​

ts
await kv.delete('user:123');

List ​

ts
const result = await kv.list({ prefix: 'user:' });
// { keys: [{ name: "user:1" }, { name: "user:2" }], list_complete: true }

This step pages through keys with limit and cursor.

ts
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 ​

ts
const result = await kv.getWithMetadata<User, { updatedBy: string }>('user:123');
// { value: User | null, metadata: { updatedBy: string } | null }

Typed maps ​

This step creates a typed client for one collection. kv.map() scopes it with a key prefix.

ts
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 adds the "sessions:" prefix to every key. It strips the prefix when listing.

ts
const result = await sessions.list();
// keys: [{ name: "abc" }, { name: "def" }]  (prefix stripped)

Maps have the base client's methods: get, put, delete, list and getWithMetadata. Values are typed and keys are prefixed.

For anything else, use the raw KVNamespace at c.env.KV in a route handler.

Next steps ​

implemented.stream AI