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";23// Set a value4await kv.set("user:123", { name: "Alice", role: "admin" });56// Get a value7const user = await kv.get("user:123");8console.log(user); // { name: "Alice", role: "admin" }910// Delete a value11await kv.delete("user:123");1213// Check if key exists14const 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 });34// Expire after 24 hours5await kv.set("daily:summary", summary, { ttl: 86400 });67// Expire after 7 days8await kv.set("weekly:report", report, { ttl: 604800 });910// No expiration (persist indefinitely)11await kv.set("config:settings", settings);Namespaces
Organize data with namespaces:
1// Use namespace to organize keys2await kv.set("settings", config, { namespace: "team-a" });3await kv.set("settings", config, { namespace: "team-b" });45// List keys in a namespace6const keys = await kv.list({ namespace: "team-a" });78// Keys with prefix9const userKeys = await kv.list({10 namespace: "team-a",11 prefix: "user:"12});Value Metadata
Get additional metadata about stored values:
1// Get value with metadata2const entry = await kv.getWithMetadata("cache:result");34console.log(entry);5// {6// key: "cache:result",7// value: { ... },8// valueType: "json",9// ttl: 3600,10// expiresAt: Date,11// createdAt: Date,12// updatedAt: Date13// }Batch Operations
Perform multiple operations efficiently:
1// Batch set multiple values2await 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]);78// Batch get multiple values9const results = await kv.batchGet(["user:1", "user:2", "user:3"]);1011for (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";23// Cache expensive AI results4const result = await relay5 .workflow("smart-cache")6 .step("check-cache", {7 // Custom step that checks cache8 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 analysis2const cacheKey = `analysis:${documentHash}`;3let analysis = await kv.get(cacheKey);45if (!analysis) {6 analysis = await workflow.run({ document });7 await kv.set(cacheKey, analysis, { ttl: 86400 }); // 24 hours8}Rate Limit Tracking
1// Track API usage per user2const key = `ratelimit:${userId}:${today}`;3const count = await kv.get(key) || 0;45if (count >= MAX_REQUESTS) {6 throw new Error("Rate limit exceeded");7}89await kv.set(key, count + 1, { ttl: 86400 }); // Reset dailyWorkflow State
1// Store multi-step workflow progress2await kv.set(`workflow:${runId}:state`, {3 currentStep: "processing",4 progress: 0.5,5 lastUpdated: new Date()6}, { ttl: 3600 });Limits
| Limit | Value |
|---|---|
| Max key length | 512 bytes |
| Max value size | 1 MB |
| Max TTL | 30 days |
| Batch operation limit | 100 keys |
See also: Telemetry | Cloud Overview