| name | kv-hyperdrive |
| description | Use Cloudflare KV for eventually consistent global cache/config and Hyperdrive for existing Postgres/MySQL access from Workers. Use when deciding cache-aside patterns, TTLs, invalidation, external DB connectivity, and Node-compatible database drivers.
|
| compatibility | Cloudflare Workers TypeScript projects using Wrangler; verify current Cloudflare APIs, limits, and pricing before production use. |
| metadata | {"source":"Architecting on Cloudflare plus official Cloudflare Developer Platform docs","generated":"2026-04-28"} |
KV and Hyperdrive
Use this skill for globally cached key/value data and for connecting Workers to existing relational databases.
KV: when to use
Use KV for:
- Public configuration and feature flags.
- Cached API responses.
- Denormalized read models.
- Low-frequency writes with high read fan-out.
- Values that tolerate eventual consistency.
Do not use KV for:
- Locks.
- Counters that must be correct.
- Inventory, balances, bookings, or permissions requiring immediate consistency.
- Coordination between clients.
KV cache-aside pattern
export interface Env {
CACHE: KVNamespace;
DB: D1Database;
}
export async function getPublicProject(env: Env, projectId: string) {
const key = `project:${projectId}:public:v1`;
const cached = await env.CACHE.get<ProjectSummary>(key, "json");
if (cached) return cached;
const project = await env.DB.prepare(
"SELECT id, name, description FROM projects WHERE id = ? AND public = 1"
).bind(projectId).first<ProjectSummary>();
if (project) {
await env.CACHE.put(key, JSON.stringify(project), { expirationTtl: 300 });
}
return project;
}
KV invalidation strategy
- Use short TTLs for data that changes frequently.
- Include schema/version suffixes in keys, such as
:v1.
- On writes, update source of truth first, then delete or replace cache.
- Design for stale reads; never rely on immediate global invalidation.
Hyperdrive: when to use
Use Hyperdrive when:
- The source of truth is an existing Postgres/MySQL-compatible database.
- Migrating fully to D1 is not currently feasible.
- You need Workers to connect to a regional database with better connection behavior.
Hyperdrive config sketch
{
"compatibility_flags": ["nodejs_compat_v2"],
"hyperdrive": [
{
"binding": "HYPERDRIVE",
"id": "REPLACE_WITH_HYPERDRIVE_ID"
}
]
}
Hyperdrive code sketch
import postgres from "postgres";
export interface Env {
HYPERDRIVE: Hyperdrive;
}
export async function listUsers(env: Env) {
const sql = postgres(env.HYPERDRIVE.connectionString);
try {
return await sql`SELECT id, email FROM users ORDER BY created_at DESC LIMIT 50`;
} finally {
await sql.end({ timeout: 1 });
}
}
Verify the recommended driver and connection pattern against current Cloudflare docs for the specific database.
Anti-patterns
- Treating KV as a strongly consistent database.
- Infinite TTL for data that must be revoked quickly.
- Cache keys that omit tenant/user/security dimensions.
- Opening external DB connections without using Hyperdrive or a documented connection strategy.
- Migrating to D1 prematurely when the existing database remains the system of record.