ctx.kv() returns the project-scoped key-value store. Call it with no arguments. Every function in the project reads and writes the same store.
Signature
kv(): KeyValueStore
Scope behavior and limits live in the key-value store guide.
KeyValueStore
interface KeyValueStore {
getItem<T = unknown>(key: string): Promise<T | null>;
setItem(key: string, value: unknown, opts?: { ttl?: number | null }): Promise<void>;
removeItem(key: string): Promise<void>;
hasItem(key: string): Promise<boolean>;
}
| Method | Returns | Notes |
|---|---|---|
getItem<T>(key) | Promise<T | null> | null when the key is missing. A stored JSON null also reads as null; use hasItem to disambiguate. |
setItem(key, value, opts?) | Promise<void> | Accepts any JSON-serializable value. Pass opts.ttl in seconds to set an expiry; see below. |
removeItem(key) | Promise<void> | Deletes the key. |
hasItem(key) | Promise<boolean> | Existence check without fetching the value. |
Setting an expiry
setItem takes an optional third argument, { ttl }, a time to live in seconds:
await kv.setItem('session:abc', data, { ttl: 3600 });
ttl | Effect |
|---|---|
| A positive integer | Deletes the key that many seconds after the write. |
null | Clears any existing expiry. |
| Omitted | Leaves any existing expiry unchanged. |
ttl must be a positive integer, with no maximum. See the key-value store guide for the full behavior.
Example
// functions/api/v1/flags.get.ts
import { defineFunction } from '@trayai/helix-sdk';
export default defineFunction(async (ctx) => {
const kv = ctx.kv();
let flags = await kv.getItem<Record<string, boolean>>('feature_flags');
if (!flags) {
flags = { beta: false };
await kv.setItem('feature_flags', flags);
}
return { flags };
});