Skip to main content
The KV Store is a persistent key-value database built into the platform. Use it to share state across executions, sessions and agents — shopping carts, feature flags, counters, idempotency keys — without standing up your own Redis or database.
  • Tenant-scoped — all agents in your workspace read and write the same store
  • Namespaces — created implicitly on first write, no setup required
  • TTL — optional per-key expiration in seconds
  • Pattern search — find keys with glob patterns like cart:*:items
  • Any JSON value — objects, arrays, strings, numbers, booleans (up to 256 KB per entry)

KV Store vs Memory

The KV Store holds business state; Memory holds conversation context. A value you set() comes back exactly as stored, for as long as you need it — while Memory content is trimmed and summarized as the conversation grows. If you were persisting data by stuffing it into sessions or message history, the KV Store replaces that workaround. See Abandoned Cart Recovery for both working together — cart in KV, dialogue in Memory.

Quick Start

Also available as a dedicated entry point: import { KV } from '@runflow-ai/sdk/kv'.

Static Shortcuts

For one-off reads and writes, the static methods use the default namespace:

Namespaces

Namespaces isolate keys by domain. They are implicit: a namespace exists as soon as its first key is written, and disappears when its last key is deleted.
Namespace names accept letters, digits, ., _ and - (max 128 characters, must start with a letter or digit).

TTL and Expiration

Pass ttl (in seconds) to make an entry expire automatically. Expired keys behave exactly like missing keys — get() returns null, has() returns false, and listings skip them.
Setting a key without ttl clears any previous TTL — the entry becomes persistent. To keep a key expiring, pass ttl on every write.
To inspect the expiration of a key, use getEntry():
keys() and getAll() accept a glob pattern: * matches any sequence of characters, ? matches exactly one.
Structure your keys with a consistent separator (entity:id:field) so patterns stay predictable — cart:*:items, user:*:profile, order:2026-07-*.

Pagination

Listings return up to 100 items by default (max 1000). For large namespaces, use listKeys() / listEntries(), which also return the total count:

Common Patterns

Cart / conversation state with TTL

Feature flags

Idempotency / deduplication

See Abandoned Cart Recovery for a complete working project combining these patterns — KV cart state, TTL as cleanup policy, idempotent reminders, and Memory-powered follow-ups.

Managing Data in the Dashboard

Every namespace is browsable in the platform under KV Store in the sidebar:
  • Browse namespaces with live key counts
  • Filter keys with the same glob patterns (cart:*:items)
  • Inspect full JSON values and TTLs
  • Delete individual keys or clear a whole namespace

Local Development

Outside the platform, the SDK follows the same convention as Memory: with RUNFLOW_ENV=development (or RUNFLOW_LOCAL_MEMORY=true) values are stored as JSON files under .runflow/kv/ in your project — no API required.
You can also pass a provider explicitly — useful in tests:
To back the KV store with your own storage, implement the KvProvider interface (same pattern as custom memory providers).

Limits and Validation

Method Reference

All methods are also available as statics on KV (operating on the default namespace), plus KV.namespace(name) to get a scoped instance and KV.namespaces() to list namespaces.

REST API

Everything above is also exposed as authenticated REST endpoints under /api/v1/runtime/v1/kv — see the Runtime REST API reference if you’re integrating without the SDK.

Next Steps

Memory

Conversation history — use KV for state, Memory for dialogue

Tools

Read and write KV state from custom tools

Abandoned Cart Recovery

Complete project: KV cart state + Memory follow-ups

Schedule

Combine KV state with scheduled follow-ups