zudo-cloudflare-wisdom

Type to search...

to open search from anywhere

KV(キーバリュー)

作成2026年4月4日更新2026年5月28日Takeshi Takatsudo

Cloudflare KV ネームスペースの使用パターン

概要

KV はグローバルで低レイテンシのキーバリューストア。結果整合性 — 書き込みは約60秒以内にグローバルに伝播するが、その間は古いデータを返す可能性がある。

セットアップ

ネームスペースの作成

npx wrangler kv namespace create "MY_KV"

出力されたネームスペース ID を wrangler.toml に追加:

[[kv_namespaces]]
binding = "MY_KV"
id = "abc123def456ghi789"

関数での使用

interface Env {
  MY_KV: KVNamespace;
}

// 読み取り
const value = await env.MY_KV.get("key");
const json = await env.MY_KV.get("key", { type: "json" });

// 書き込み
await env.MY_KV.put("key", "value");
await env.MY_KV.put("key", JSON.stringify(data));

// 有効期限付き書き込み(TTL は秒)
await env.MY_KV.put("key", "value", { expirationTtl: 3600 });

// 削除
await env.MY_KV.delete("key");

// キーの一覧
const list = await env.MY_KV.list({ prefix: "logs:" });

💡 重要でない書き込みには waitUntil を使用

context.waitUntil() はレスポンス送信後に非同期処理を実行できる。ロギング、アナリティクス、その他の重要でない書き込みに使用する。

パターン: 会話状態管理

TTL ベースの自動クリーンアップ付きで、スレッドごとのマルチターン会話履歴を保存する:

const CONVERSATION_TTL = 86400; // 24 時間

interface ConversationHistory {
  messages: Array<{ role: string; content: string }>;
}

// Load with typed JSON deserialization
const key = `conv:${threadId}`;
const stored = await env.KV.get<ConversationHistory>(key, "json");
const history = stored ?? { messages: [] };

// Append new message
history.messages.push({ role: "user", content: userMessage });

// Save with TTL -- old conversations auto-expire
await env.KV.put(key, JSON.stringify(history), {
  expirationTtl: CONVERSATION_TTL,
});

設計のポイント:

  • conv:{threadId} のような構造化キーで識別しやすくする
  • get()"json" 型パラメータでデシリアライズを自動化
  • TTL により古い会話が永遠に蓄積されない

パターン: レート制限

TTL 有効期限付き KV カウンターによるユーザーごとのレート制限:

const RATE_LIMIT = 30;
const RATE_WINDOW = 86400; // 24 時間

async function checkRateLimit(
  env: Env,
  userId: string,
): Promise<boolean> {
  const key = `rate:${userId}`;
  const count = await env.KV.get<number>(key, "json") ?? 0;

  if (count >= RATE_LIMIT) return false;

  await env.KV.put(key, JSON.stringify(count + 1), {
    expirationTtl: RATE_WINDOW,
  });
  return true;
}

⚠️ KV のレート制限は近似的

KV は結果整合性のため、高い同時実行数では数件の余分なリクエストが通過する可能性がある。ボットや API のレート制限としては問題ないが、正確なカウントが必要な場合は Durable Objects を使用する。

注意点

  • 結果整合性: 書き込み直後の読み取りは古いデータを返す可能性がある
  • 512バイトのキー制限: キーは512バイトを超えられない
  • 25 MiB の値制限: 値は25 MiB を超えられない
  • リストのページネーション: list() は1回の呼び出しで最大1000キーを返す