Virke KV

Fast key-value storage at the edge. Virke KV is a thin wrapper over Fastly KV Store, namespaced per project.

Performance

Operation Latency
Read (warm POP) 4–10ms
Write ~450ms
List keys 10–30ms
Delete ~450ms

CLI Usage

Set a value

virke kv set user:123 '{"name": "Alice", "email": "alice@example.com"}'

With a TTL (time-to-live) in seconds:

virke kv set session:abc token-value --ttl 3600

Get a value

virke kv get user:123

List keys

virke kv list
virke kv list --prefix user:

Delete a key

virke kv delete user:123

SDK Usage (from Virke Run)

With Hono

import { Hono } from "hono";
import { virke } from "@virke/runtime/hono";

const { fire, middleware, Bindings } = virke({ kv: "my-app-kv" });
const app = new Hono<{ Bindings: typeof Bindings }>();

app.use("*", middleware);

// String values
app.get("/session/:id", async (c) => {
  const session = await c.env.kv.get(
    `session:${c.req.param("id")}`
  );
  if (!session) return c.json({ error: "Not found" }, 404);
  return c.text(session);
});

// JSON values
app.get("/user/:id", async (c) => {
  const user = await c.env.kv.getJson(`user:${c.req.param("id")}`);
  if (!user) return c.json({ error: "Not found" }, 404);
  return c.json(user);
});

// Write with TTL
app.post("/session", async (c) => {
  const { userId, token } = await c.req.json();
  await c.env.kv.set(`session:${token}`, userId, { ttl: 3600 });
  return c.json({ ok: true });
});

// List keys with pagination
app.get("/keys", async (c) => {
  const prefix = c.req.query("prefix");
  const cursor = c.req.query("cursor");
  const result = await c.env.kv.list({ prefix, limit: 100, cursor });
  return c.json(result);
});

fire(app);

KV binding API

interface VirkeKV {
  get(key: string): Promise<string | null>;
  getJson<T = unknown>(key: string): Promise<T | null>;
  getBytes(key: string): Promise<ArrayBuffer | null>;
  getWithMetadata(key: string): Promise<{ value: string | null; generation: number }>;
  set(key: string, value: string | ArrayBuffer, options?: { ttl?: number; generation?: number }): Promise<void>;
  setJson(key: string, value: unknown, options?: { ttl?: number; generation?: number }): Promise<void>;
  delete(key: string): Promise<void>;
  list(options?: {
    prefix?: string;
    limit?: number;
    cursor?: string;
  }): Promise<{ keys: string[]; cursor: string | undefined }>;
}

Use Cases

Session storage

// Create session (expires in 24 hours)
await env.kv.setJson(`session:${sessionId}`, {
  userId: user.id,
  email: user.email,
  createdAt: Date.now(),
}, { ttl: 86400 });

// Validate session
const session = await env.kv.getJson(`session:${sessionId}`);
if (!session) {
  return new Response("Unauthorized", { status: 401 });
}

Feature flags

const flags = await env.kv.getJson("feature-flags") ?? {};
if (flags.newCheckout) {
  // Render new checkout flow
}

Rate limiting

const key = `ratelimit:${clientIp}:${minute}`;
const count = await env.kv.get(key);
const current = count ? parseInt(count) : 0;

if (current >= 100) {
  return new Response("Too Many Requests", { status: 429 });
}

await env.kv.set(key, String(current + 1), { ttl: 60 });

Optimistic locking

// Read with generation number
const { value, generation } = await env.kv.getWithMetadata("counter");
const count = value ? parseInt(value) : 0;

// Write with generation check — fails if another writer changed the value
await env.kv.set("counter", String(count + 1), { generation });

Key Naming Conventions

user:{id}            -> User profile data
session:{token}      -> Session data
cache:{url-hash}     -> Cached responses
ratelimit:{ip}:{min} -> Rate limit counters
flag:{name}          -> Feature flags

Limitations

  • Key size — maximum 1,024 bytes
  • Value size — maximum 25 MB per value
  • Eventual consistency — writes visible globally within a few seconds
  • No atomic increment — use read-modify-write with optimistic locking via generation numbers
  • List prefix restrictions — prefixes cannot contain ! " $ % & ( ) * + , / \ : < = > @ [ ] { }

Further Reading

  • Virke Run — Build compute functions that use Virke KV
  • CLI Commands — Full virke kv command reference