KV Store

Persistent key-value storage with TTL support for sharing state between workflow runs.

KV Store requires Cloud features to be enabled.

Overview

The KV Store provides a simple way to persist data across workflow runs. Use it to cache expensive computations, store configuration, maintain state, or share data between workflows.

Basic Operations

1import { kv } from "@relayplane/sdk";
2
3// Set a value
4await kv.set("user:123", { name: "Alice", role: "admin" });
5
6// Get a value
7const user = await kv.get("user:123");
8console.log(user); // { name: "Alice", role: "admin" }
9
10// Delete a value
11await kv.delete("user:123");
12
13// Check if key exists
14const exists = await kv.get("user:123");
15if (exists === null) {
16 console.log("Key not found");
17}

Time-To-Live (TTL)

Set expiration times for automatic cleanup:

1// Expire after 1 hour (3600 seconds)
2await kv.set("cache:result", data, { ttl: 3600 });
3
4// Expire after 24 hours
5await kv.set("daily:summary", summary, { ttl: 86400 });
6
7// Expire after 7 days
8await kv.set("weekly:report", report, { ttl: 604800 });
9
10// No expiration (persist indefinitely)
11await kv.set("config:settings", settings);

Namespaces

Organize data with namespaces:

1// Use namespace to organize keys
2await kv.set("settings", config, { namespace: "team-a" });
3await kv.set("settings", config, { namespace: "team-b" });
4
5// List keys in a namespace
6const keys = await kv.list({ namespace: "team-a" });
7
8// Keys with prefix
9const userKeys = await kv.list({
10 namespace: "team-a",
11 prefix: "user:"
12});

Value Metadata

Get additional metadata about stored values:

1// Get value with metadata
2const entry = await kv.getWithMetadata("cache:result");
3
4console.log(entry);
5// {
6// key: "cache:result",
7// value: { ... },
8// valueType: "json",
9// ttl: 3600,
10// expiresAt: Date,
11// createdAt: Date,
12// updatedAt: Date
13// }

Batch Operations

Perform multiple operations efficiently:

1// Batch set multiple values
2await kv.batchSet([
3 { key: "user:1", value: { name: "Alice" } },
4 { key: "user:2", value: { name: "Bob" } },
5 { key: "user:3", value: { name: "Charlie" }, ttl: 3600 }
6]);
7
8// Batch get multiple values
9const results = await kv.batchGet(["user:1", "user:2", "user:3"]);
10
11for (const result of results) {
12 if (result.value) {
13 console.log(`${result.key}: ${result.value.name}`);
14 }
15}

Using KV in Workflows

Access the KV store from within workflows:

1import { relay, kv } from "@relayplane/sdk";
2
3// Cache expensive AI results
4const result = await relay
5 .workflow("smart-cache")
6 .step("check-cache", {
7 // Custom step that checks cache
8 handler: async (input) => {
9 const cached = await kv.get(`cache:${input.key}`);
10 return { cached, hit: cached !== null };
11 }
12 })
13 .step("compute", {
14 condition: "!steps['check-cache'].output.hit"
15 })
16 .with("openai:gpt-4o")
17 .depends("check-cache")
18 .prompt("Process: {{input.data}}")
19 .step("save-cache", {
20 condition: "!steps['check-cache'].output.hit",
21 handler: async (input, steps) => {
22 await kv.set(`cache:${input.key}`, steps.compute.output, { ttl: 3600 });
23 return steps.compute.output;
24 }
25 })
26 .depends("compute")
27 .run({ key: "unique-id", data: "..." });

Common Use Cases

Result Caching

1// Cache expensive AI analysis
2const cacheKey = `analysis:${documentHash}`;
3let analysis = await kv.get(cacheKey);
4
5if (!analysis) {
6 analysis = await workflow.run({ document });
7 await kv.set(cacheKey, analysis, { ttl: 86400 }); // 24 hours
8}

Rate Limit Tracking

1// Track API usage per user
2const key = `ratelimit:${userId}:${today}`;
3const count = await kv.get(key) || 0;
4
5if (count >= MAX_REQUESTS) {
6 throw new Error("Rate limit exceeded");
7}
8
9await kv.set(key, count + 1, { ttl: 86400 }); // Reset daily

Workflow State

1// Store multi-step workflow progress
2await kv.set(`workflow:${runId}:state`, {
3 currentStep: "processing",
4 progress: 0.5,
5 lastUpdated: new Date()
6}, { ttl: 3600 });

Limits

LimitValue
Max key length512 bytes
Max value size1 MB
Max TTL30 days
Batch operation limit100 keys