@farfarawaylabs/chat-sdk-adapter-kv
v0.2.0
Published
Cloudflare KV state adapter for the Vercel Chat SDK
Downloads
155
Maintainers
Readme
@farfarawaylabs/chat-sdk-adapter-kv
Cloudflare KV state adapter for the Vercel Chat SDK. A drop-in replacement for the Redis state adapter, designed for Cloudflare Workers.
Installation
npm install @farfarawaylabs/chat-sdk-adapter-kvUsage
Pass your KV namespace binding to createCloudflareKVState():
import { Chat } from "chat";
import { createCloudflareKVState } from "@farfarawaylabs/chat-sdk-adapter-kv";
export default {
async fetch(request: Request, env: Env) {
const bot = new Chat({
userName: "mybot",
adapters: { /* ... */ },
state: createCloudflareKVState({ kv: env.CHAT_KV }),
});
},
};Wrangler configuration
Add a KV namespace binding in your wrangler.toml:
[[kv_namespaces]]
binding = "CHAT_KV"
id = "your-kv-namespace-id"Key prefix
All keys are namespaced under a configurable prefix (default: "chat-sdk"):
const state = createCloudflareKVState({
kv: env.CHAT_KV,
keyPrefix: "my-bot",
});Custom logger
const state = createCloudflareKVState({
kv: env.CHAT_KV,
logger: myLogger,
});Configuration
| Option | Required | Description |
| ----------- | -------- | ---------------------------------------------- |
| kv | Yes | Cloudflare KV namespace binding |
| keyPrefix | No | Prefix for all keys (default: "chat-sdk") |
| logger | No | Logger instance (defaults to ConsoleLogger) |
Key structure
{keyPrefix}:sub:{threadId} - Subscription marker for a thread
{keyPrefix}:lock:{threadId} - Lock key with TTL
{keyPrefix}:cache:{key} - Cached key-value entry
{keyPrefix}:list:{key} - List stored as JSON arrayFeatures
| Feature | Supported | | ------------------------ | --------- | | Persistence | Yes | | Subscriptions | Yes | | Key-value caching | Yes | | Key prefix namespacing | Yes | | Best-effort locking | Yes | | Atomic distributed locks | No |
Limitations
Cloudflare KV has different characteristics than Redis. Be aware of these trade-offs:
Eventual consistency
KV is eventually consistent. Reads may return stale data for up to 60 seconds after a write. This can affect isSubscribed checks and lock visibility across workers in different regions.
Non-atomic locking
Lock operations (acquireLock, releaseLock, extendLock) and setIfNotExists use read-then-write patterns that are not atomic. Under high concurrency, two workers could both acquire the same lock. If you need reliable distributed locking, use Cloudflare Durable Objects instead.
Minimum TTL
KV's minimum expiration TTL is 60 seconds. Shorter TTLs are enforced logically via stored expiration timestamps — the adapter will treat the lock as expired, but the KV key won't be physically deleted until at least 60 seconds have passed.
Concurrent list appends
appendToList reads the full list, modifies it in memory, and writes it back. Concurrent appends from different workers may overwrite each other. For high-write list workloads, consider using Durable Objects or D1 instead.
When to use this adapter
This adapter is a good fit when:
- You are running on Cloudflare Workers and want a simple state backend
- Your workload has low to moderate concurrency
- Eventual consistency is acceptable for your use case
- You don't need strict distributed locking guarantees
If you need strong consistency or atomic operations, consider Durable Objects or D1 as your state backend.
License
MIT
