+ 作るログイン
1 / 13
Cloudflare のすべて ― 1機能ずつ、仕組みと存在理由から / 全35本

Cloudflare 20:KV ― 世界中から速く読める、キーと値の置き場

発行
アニメモ公式
版
第2版
改訂
コマ
全13

Workers KV を、なぜ「読み込みが速く、書き込みが遅れて行き渡る」のかという仕組みから説明します。拠点ごとのキャッシュと中央の保管庫、最大60秒ほどの結果整合性、向いている用途(設定・機能フラグ・セッション)と向いていない用途(カウンター)、名前空間の作り方、get / put / list のコード、cacheTtl、料金と制限、他の置き場との使い分けまで。

世界中の Worker から、同じ設定を速く読みたい

18号で見たとおり、Worker は世界中の拠点で動きます。東京の利用者には東京で、サンパウロの利用者にはサンパウロで、あなたのコードが走ります。

では、その Worker がデータを読みたくなったらどうでしょう。たとえば「サイトのテーマ色」「新しい機能をオンにするかどうか」「古い URL から新しい URL への対応表」といった設定です。

普通に考えると、データベースを1つ用意して、Worker から読みに行きます。ところが、データベースは1か所にあります。東京に置いたら、サンパウロの Worker は、設定を1つ読むたびに地球の反対側まで往復することになります。せっかく利用者の近くでコードを動かしているのに、データのところで遠回りしてしまうのです。

しかも、こうした設定はほとんど変わりません。テーマ色を変えるのは月に1回かもしれません。それなのに、1秒に何百回も同じ値を遠くまで取りに行くのは、もったいない話です。データベースにも、無駄な負荷がかかります。

欲しいのは、「めったに変わらない値を、世界中のどこからでも近くで読める」置き場です。それが、この号で扱う Workers KV(以下 KV)です。

※この号の内容は 2026年9月時点の情報をもとにしています。料金や上限は変わることがあるので、使うときは必ず公式のドキュメントで確かめてください。

  • Cloudflare のすべて 20 ― KV
  • 1 / 13
  • 世界中の Worker から、同じ設定を速く読みたい
  • 1か所のデータベース
  • 東京の Worker
  • ロンドンの Worker
  • NYの Worker
  • サンパウロの Worker
  • サンパウロの Worker が、毎回地球の反対側まで設定を読みに行く
  • ほとんど変わらない設定なのに、読むたびに遅い。データベースの負荷も増える
  • Worker は世界中で動くのに、データベースが1か所だと毎回遠くまで行く。

一言でいうと:世界中から速く読める、キーと値の置き場

KV は、キー(名前)と値の組を保存する、とても単純な置き場です。KV は Key-Value の頭文字です。

キー値
theme青
flag:new-editortrue
session:9f2c…{"user":"u_12"}
redirect:/old/new

できることは、ほぼ次の4つだけです。

操作意味
get(キー)値を読む
put(キー, 値)値を書く(上書き)
delete(キー)消す
list(先頭の文字)キーの一覧を取る

表の列も、SQL も、検索もありません。「この名前の値をください」「この名前でこの値を覚えておいて」だけです。その代わり、読み込みが世界中どこからでも速いという、1つの長所に特化しています。

KV は、読み込みがとても多く、書き込みが少ない用途のために作られています。どのくらい極端かは、後で見る無料枠の数字(読み込みは書き込みの100倍)にも表れています。次のページから、なぜ読み込みが速く、なぜ書き込みに弱いのかを、仕組みから見ていきます。

  • Cloudflare のすべて 20 ― KV
  • 2 / 13
  • 一言でいうと:世界中から速く読める、キーと値の置き場
  • キー
  • 値
  • theme
  • 青
  • flag:new-editor
  • true
  • session:9f2c…
  • {"user":"u_12"}
  • redirect:/old
  • /new
  • get(キー) で読み、put(キー, 値) で書く。表も SQL も無い
  • 読んだ値は各拠点が覚えておくので、2回目からは近くで返る
  • 名前(キー)で値を出し入れするだけ。読み込み中心の用途向け。

読むとき:近くの拠点が覚えていれば、その場で返る

KV の値は、大もとの中央の保管庫にしまわれています。図の上の紫の箱です(実際には何段かの層になっていますが、ここでは単純にしています)。

東京の Worker が theme を読もうとしたとします。

回何が起きるか
1回目東京の拠点には、まだ theme が無い。中央の保管庫まで取りに行く。取ってきた値を、東京の拠点がしばらく覚えておく
2回目から東京の拠点が覚えているので、拠点の中ですぐ返る。中央までは行かない

これは、02号で見た CDN のキャッシュとまったく同じ考え方です。よく読まれるキーほど、拠点が覚えている時間のほとんどを「その場で返す」ことに使えるので、効果が大きくなります。

世界中の拠点が、それぞれ自分の近くの利用者のために値を覚えます。東京の拠点は東京の Worker のために、サンパウロの拠点はサンパウロの Worker のために。結果として、人気のあるキーは、世界中どこからでも近くで読めるようになります。

逆に、めったに読まれないキーは、読むたびに中央まで行くことになり、それほど速くありません。KV は「同じキーが何度も読まれる」ときに真価を発揮する置き場です。

  • Cloudflare のすべて 20 ― KV
  • 3 / 13
  • 読むとき:近くの拠点が覚えていれば、その場で返る
  • 中央の保管庫
  • theme = 青
  • 東京の拠点
  • ロンドンの拠点
  • NYの拠点
  • サンパウロの拠点
  • theme = 青
  • 1回目:東京の拠点に無い → 中央から取ってきて、しばらく覚えておく
  • 2回目から:東京の中で返る(速い)。よく読まれるキーほど効果が大きい
  • 1回目だけ中央へ。その後は拠点の中で返るから速い。

書くとき:まず中央へ。他の拠点はしばらく古い値のまま

では、値を書き換えるとどうなるでしょうか。東京の Worker が、theme を「青」から「赤」に書き換えたとします。

書き込みは、中央の保管庫に送られます。中央の値は「赤」になります。書き込んだ東京の拠点も、すぐに「赤」が見えるようになります。

問題は、他の拠点です。ロンドン・NY・サンパウロの拠点は、前に読んだ「青」を覚えたままです。拠点は「覚えている間は中央に確かめに行かない」ことで速さを出しているので、中央の値が変わったことに、すぐには気づきません。

その結果、書き換えた直後には、こういうことが起きます。

拠点見える値
中央・東京赤(新しい)
ロンドン・NY・サンパウロ青(古い)

同じキーを同じ瞬間に読んでも、どの拠点で読んだかによって、違う値が返るのです。

普通のデータベースに慣れていると、これは奇妙に感じます。「書いたのに、読んだら古い値が返る」のですから。でも、これが KV の速さの代償です。拠点が毎回「中央の値は変わっていないか」を確かめていたら、結局遠くまで往復することになり、速さが失われてしまいます。

  • Cloudflare のすべて 20 ― KV
  • 4 / 13
  • 書くとき:まず中央へ。他の拠点はしばらく古い値のまま
  • 中央の保管庫
  • theme = 赤
  • 東京の拠点
  • ロンドンの拠点
  • NYの拠点
  • サンパウロの拠点
  • theme = 赤
  • theme = 青
  • theme = 青
  • theme = 青
  • 東京で「赤」に書き換えた。中央と東京はすぐ「赤」になる
  • ロンドン・NY・サンパウロは、覚えている「青」をまだ返す(古い値)
  • 書いた拠点はすぐ新しい値。遠くの拠点は古い値をしばらく返す。

行き渡るまで、最大でおよそ60秒

では、古い値はいつまで返るのでしょうか。

各拠点が値を覚えておく時間には、限りがあります。その時間が切れると、拠点は次に読まれたときに中央へ取りに行き、新しい「赤」を覚え直します。こうして、書き込みは、最大でおよそ60秒で世界中に行き渡ります(後で見る cacheTtl を長くした場合は、その分だけ遅くなります)。

このように、「書いた直後は場所によって違う値が見えるが、いつかは必ず揃う」という性質を、結果整合性(eventual consistency)と呼びます。反対に、「書いた瞬間から、どこで読んでも新しい値が見える」性質を強い整合性と呼びます。

性質読み込み書き込み直後
結果整合性(KV)世界中で速いしばらく場所によって違う
強い整合性(Durable Objects・D1)1か所に確かめに行くどこで読んでも同じ

どちらが優れているということはありません。何を優先するかの違いです。KV は、「すぐ揃う」ことをあきらめる代わりに、「世界中で速く読める」ことを手に入れています。

設定値やフラグなら、変更が世界中に届くのに数十秒かかっても、ほとんどの場合は困りません。KV を使うかどうかは、「この値は、少しの間古くても困らないか」で判断します。

  • Cloudflare のすべて 20 ― KV
  • 5 / 13
  • 行き渡るまで、最大でおよそ60秒
  • 中央の保管庫
  • theme = 赤
  • 東京の拠点
  • ロンドンの拠点
  • NYの拠点
  • サンパウロの拠点
  • theme = 赤
  • theme = 赤
  • theme = 赤
  • theme = 赤
  • 拠点が覚えている時間が切れると、中央に取りに行き、新しい値になる
  • その代わり、読み込みは世界中で速い。速さと引き換えに「すぐ揃う」を捨てている
  • これが「結果整合性」。いつかは揃うが、揃うまでの間は拠点ごとに違う。

向いている用途・向いていない用途

ここまでの仕組みから、KV に向く用途と、向かない用途がはっきりします。

向いている理由
サイトの設定・機能フラグめったに変わらず、全リクエストで読まれる
リダイレクトの対応表大量の URL を、キーで一発で引ける
API の返事のキャッシュ外部 API の結果を数分だけ覚えておく
ログインのセッション書くのはログイン時の1回、読むのは毎回
向いていない理由
いいね数などのカウンター読んで +1 して書く間に、他の拠点も同じことをすると数え漏れる
在庫・残高取り合いがあり、古い値で判断すると売りすぎる
1秒に何度も書くキー同じキーへの書き込みは1秒に1回までの制限がある
検索や集計条件で探す仕組みが無い

セッションは、「ログアウトした直後に、別の拠点ではまだログインしている扱いになる」ことがありえます。多くのサイトでは問題になりませんが、厳密さが要るなら別の置き場を検討しましょう。

向いていない側の用途には、別の答えがあります。数える・取り合うものは Durable Objects(21号)、検索・集計が要るものは D1(23号)です。

  • Cloudflare のすべて 20 ― KV
  • 6 / 13
  • 向いている用途・向いていない用途
  • 向いている
  • 向いていない
  • サイトの設定・機能フラグ
  • いいね数などのカウンター
  • リダイレクトの対応表
  • 在庫・残高(取り合いがある)
  • API の返事のキャッシュ
  • 1秒に何度も書くキー
  • ログインのセッション
  • 検索や集計(SQL が要る)
  • 右側は Durable Objects(21号)や D1(23号)へ
  • 「たまに書き、たくさん読む。少し古くても困らない」なら KV。

導入:名前空間を作り、Worker につなぐ

KV の入れ物は名前空間(namespace)と呼ばれます。1つの名前空間の中に、キーと値の組がたくさん入ります。用途ごとに名前空間を分けておくと、整理しやすくなります。

名前空間は、wrangler のコマンドで作れます。

$ npx wrangler kv namespace create CONFIG

実行すると、作られた名前空間の ID が表示されます。これを Worker の設定ファイルに、バインディング(18号)として書きます。

jsonc
{
  "kv_namespaces": [
    { "binding": "CONFIG", "id": "<名前空間の ID>" }
  ]
}

binding に書いた名前が、コードの env に入る名前になります。この例なら env.CONFIG です。

方法できること
wrangler のコマンド名前空間を作る、値を書く・読む・消す(wrangler kv key put など)
管理画面「Storage & Databases」の KV から、名前空間を作る、値を確かめる・直す
Worker のコード本番の読み書き

手元で wrangler dev を使うと、KV は手元の模擬版につながります。本番の値を汚さずに試せます。本番の名前空間につないで試したいときは、そのための設定もあります。

TypeScript を使うなら、npx wrangler types を実行すると、env.CONFIG の型(KVNamespace)が自動で作られます。

  • Cloudflare のすべて 20 ― KV
  • 7 / 13
  • 導入:名前空間を作り、Worker につなぐ
  • $ npx wrangler kv namespace create CONFIG
  • → 表示された id を wrangler.jsonc に書く
  • "kv_namespaces": [
  • { "binding": "CONFIG", "id": "<名前空間の ID>" }
  • ]
  • 管理画面の「Storage & Databases → KV」からも作れる。値の追加・確認もできる
  • KV の入れ物は「名前空間」。作って、ID を設定に書けば env から使える。

使い方:get・put・delete・list

Worker のコードからは、env.CONFIG に対して、get・put・delete・list を呼びます。どれも非同期なので await を付けます。

ts
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // 読む。無ければ null
    const theme = (await env.CONFIG.get("theme")) ?? "青";

    // JSON として読む
    const flags = await env.CONFIG.get<{ newEditor: boolean }>("flags", "json");

    // 書く。expirationTtl は「この秒数が過ぎたら自動で消す」
    const id = crypto.randomUUID();
    await env.CONFIG.put(`session:${id}`, JSON.stringify({ user: "u_12" }), {
      expirationTtl: 60 * 60,
    });

    // 先頭の文字でキーの一覧を取る
    const { keys } = await env.CONFIG.list({ prefix: "session:" });

    return Response.json({ theme, flags, sessions: keys.length });
  },
};

いくつか押さえておきたい点があります。

機能使いどころ
"json" を渡す文字列ではなく、JSON を読み込んだ形で受け取る。ほかに "arrayBuffer"・"stream" もある
expirationTtlセッションや一時的なキャッシュを、消し忘れなく自動で消す
list の prefixsession: のように、キーの頭に種類を付けておくと、種類ごとに一覧できる
メタデータput のときに小さな付箋を付けられ、list の結果にも載る

キーの付け方には、「種類:ID」のように区切りを入れておくのがおすすめです。KV には表が無いので、キーの名前が整理の道具になります。

  • Cloudflare のすべて 20 ― KV
  • 8 / 13
  • 使い方:get・put・delete・list
  • const theme = await env.CONFIG.get("theme"); // 無ければ null
  • const flags = await env.CONFIG.get("flags", "json"); // JSON として読む
  • await env.CONFIG.put("theme", "赤");
  • await env.CONFIG.put(`session:${id}`, body, { expirationTtl: 3600 });
  • await env.CONFIG.delete("theme");
  • const { keys } = await env.CONFIG.list({ prefix: "session:" });
  • expirationTtl:秒数が過ぎたら自動で消える(セッションに便利)
  • どれも await で呼ぶ。値は文字列・JSON・バイナリで出し入れできる。

cacheTtl:拠点に覚えさせる時間を延ばす

KV の読み込みには、cacheTtl という指定ができます。「この値を、拠点に何秒覚えさせるか」です。

ts
const theme = await env.CONFIG.get("theme", { cacheTtl: 3600 }); // 1時間

これまでの図で見たとおり、拠点が値を覚えている間は、中央まで行かずに速く返せます。めったに変わらない値なら、覚える時間を長くするほど、中央へ行く回数が減り、読み込みはさらに速くなります。

ただし、これは両刃の剣です。覚える時間を1時間にすると、値を書き換えたときに、他の拠点へ行き渡るのにも最大で1時間かかるようになります。「最大60秒ほどで行き渡る」という話は、既定の設定のときのものです。

cacheTtl読み込み変更が届くまで
既定のまま速い最大60秒ほど
長くする(例:1時間)さらに速い最大でその時間

cacheTtl には最小値があり、それより短くはできません。「書いたらすぐ全部の拠点に届いてほしい」という要求は、そもそも KV の設計と合わないので、その場合は Durable Objects(21号)を検討します。

使い分けの目安は、「その値が変わったとき、どのくらい古い値が見えていても許されるか」です。サイトのロゴの場所のように、1時間古くても誰も困らない値なら長く、機能フラグのように早く切り替えたい値なら既定のまま、と決めます。

  • Cloudflare のすべて 20 ― KV
  • 9 / 13
  • cacheTtl:拠点に覚えさせる時間を延ばす
  • 中央の保管庫
  • theme = 青
  • 東京の拠点
  • ロンドンの拠点
  • NYの拠点
  • サンパウロの拠点
  • theme = 青
  • theme = 青
  • theme = 青
  • theme = 青
  • await env.CONFIG.get("theme", { cacheTtl: 3600 }); // 1時間、拠点が覚えておく(変更が届くのも遅くなる)
  • めったに変わらない値は長く覚えさせる。中央へ行く回数が減る。

料金と制限:読み込みは多く、書き込みは少なく

KV の料金は、操作の回数と保存している量で決まります。2026年9月時点の主な数字は次のとおりです。料金・上限は変わるので、必ず公式の Pricing と Limits のページで確かめてください。

項目FreePaid(Workers Paid)
読み込み1日10万回月1,000万回込み、超えた分は従量
書き込み1日1,000回月100万回込み、超えた分は従量
削除・一覧それぞれ1日1,000回それぞれ月100万回込み、超えた分は従量
保存できる量1GB1GB 込み、超えた分は従量

Free の数字を見ると、読み込みは書き込みの100倍です。これは、KV が「たまに書き、たくさん読む」ために作られていることをそのまま表しています。Free では、上限を超えるとその種類の操作がエラーになり、次の日(UTC の0時)に回数が戻ります。

料金とは別に、仕組みから来る制限もあります。

制限中身
同じキーへの書き込み1秒に1回まで。超えるとエラーになることがある
キーの長さ・値の大きさどちらにも上限がある。大きなファイルは R2(22号)へ
行き渡るまでの時間最大60秒ほど(cacheTtl を長くすればその分延びる)

特に「同じキーへの書き込みは1秒に1回まで」は、カウンターのような使い方ができない、もう1つの理由です。

  • Cloudflare のすべて 20 ― KV
  • 10 / 13
  • 料金と制限:読み込みは多く、書き込みは少なく
  • 項目
  • Free
  • Paid(Workers Paid)
  • 読み込み
  • 1日 10万回
  • 月1,000万回込み、超過は従量
  • 書き込み・削除・一覧
  • それぞれ1日 1,000回
  • 月100万回込み、超過は従量
  • 保存できる量
  • 1GB
  • 1GB 込み、超過は従量
  • 同じキーへの書き込み
  • 1秒に1回まで
  • 1秒に1回まで
  • 2026年9月時点。上限・料金は変わるので、公式の Pricing と Limits のページで確かめること
  • 無料枠も「読み100に対して書き1」。書き込みの多い用途は向かない。

よくある落とし穴

KV でよくつまずく点をまとめます。

落とし穴何が起きるかどうするか
読んで +1 して書く同時に2つの Worker が読むと、どちらも同じ値に +1 して書くので、1回分消えるカウンターは Durable Objects(21号)で
書いた直後に別の拠点で読む古い値が返る。「保存したのに反映されない」と勘違いする書いた本人には、書いた値をそのまま返す作りにする
同じキーに何度も書く1秒に1回を超えるとエラー書き込みをまとめる、キーを分ける
アクセスの記録に使うFree の書き込みは1日1,000回。すぐ使い切るログは 32号の仕組みや、Queues(24号)経由で別の置き場へ
大きな値を入れる上限にかかる。読むたびに大きなデータを運ぶファイルは R2(22号)へ置き、KV には場所だけ書く

1つ目の「読んで +1 して書く」は、KV に限らず、取り合い(競合) の典型的な失敗です。手元で1人で試しているときは正しく動くので、本番でアクセスが増えてから初めて気づくことが多いのが厄介なところです。

KV を選ぶときは、いつも2つを自問しましょう。「この値は、少し古くても困らないか」「同じキーを、何人もが同時に書き換えることはないか」。両方が「はい、困らない」「いいえ、ない」なら、KV は最良の選択です。

  • Cloudflare のすべて 20 ― KV
  • 11 / 13
  • よくある落とし穴
  • 読んで +1 して書く:同時に来ると数え漏れる
  • 書いた直後に別の拠点で読む:古い値が返ることがある
  • 同じキーに何度も書く:1秒に1回を超えるとエラー
  • 無料枠の書き込み1日1,000回:アクセス記録には足りない
  • 変わらない値は cacheTtl を長く、数えるなら DO へ
  • KV は速いが「すぐ揃う」も「取り合い」もできない。そこを前提に使う。

他の置き場との使い分け

Cloudflare には、データの置き場がいくつもあります。KV を他と比べると、選び方が見えてきます。

置き場号得意なこと整合性
KV20たまに書き、世界中でたくさん読む結果整合性(最大60秒ほど遅れる)
Durable Objects211か所で正しく数える・取り合いを捌く強い整合性
D123SQL で探す・並べる・集計する強い整合性(読み取りの複製もある)
R222画像・動画・バックアップなどのファイル強い整合性

迷ったときは、次の順に考えます。

問い答えが「はい」なら
中身はファイルかR2
条件で探したり、集計したりするかD1
同時に書き換える人がいるか、すぐ揃う必要があるかDurable Objects
どれでもなく、読み込みが中心かKV

組み合わせて使うことも普通です。たとえば、画像そのものは R2 に置き、「どの画像を表示するか」という設定だけを KV に置く。記事は D1 に置き、よく読まれる記事の組み立て済みの HTML を KV にキャッシュする、といった具合です。

どれも Worker からはバインディングでつなぎ、env.名前 で呼び出します(18号)。

  • Cloudflare のすべて 20 ― KV
  • 12 / 13
  • 他の置き場との使い分け
  • KV(20)
  • Durable Objects(21)
  • たまに書き、世界中で読む
  • 1か所で正しく数える
  • D1(23)
  • R2(22)
  • SQL で探す・集計する
  • 画像や動画などのファイル
  • KV の値1つの大きさにも上限がある。大きなファイルは R2 に置き、KV には場所だけ書く
  • 迷ったら「揃う必要があるか」「SQL が要るか」「ファイルか」で選ぶ。

まとめ:KV は「世界中で速く読める、少し遅れて揃う」置き場

この号で見たことをまとめます。

項目内容
なぜあるか世界中で動く Worker から、めったに変わらない値を近くで読むため
形キーと値の組。get・put・delete・list だけ
読むとき拠点が覚えていればその場で返る。1回目だけ中央へ
書くとき中央へ。他の拠点には最大60秒ほどで行き渡る(結果整合性)
向いている設定・機能フラグ・リダイレクト表・キャッシュ・セッション
向いていないカウンター・在庫・1秒に何度も書くキー・検索
導入wrangler kv namespace create → 設定にバインディング
調整cacheTtl で覚える時間、expirationTtl で自動削除
料金読み込みの無料枠が書き込みの100倍。操作の回数と保存量で数える

KV の性質は、「速さのために、すぐ揃うことをあきらめた」の一言にまとまります。その割り切りが合う用途では、これほど簡単で速い置き場はありません。合わない用途、つまり「1か所で正しく数えたい」ときの答えが、次の21号で扱う Durable Objects です。

  • Cloudflare のすべて 20 ― KV
  • 13 / 13
  • まとめ:KV は「世界中で速く読める、少し遅れて揃う」置き場
  • 中央の保管庫
  • theme = 赤
  • 東京の拠点
  • ロンドンの拠点
  • NYの拠点
  • サンパウロの拠点
  • theme = 赤
  • theme = 赤
  • theme = 赤
  • theme = 赤
  • 読む:近くの拠点が覚えていれば、その場で返る / 書く:中央へ、最大60秒ほどで行き渡る
  • env.名前.get / put / delete / list。数える・取り合うものは Durable Objects(21号)へ
  • 読み込み中心の設定・キャッシュ・セッションに。数えるものには使わない。

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]