CLOUDFLARE / WORKERS
A BEGINNER'S GUIDE · 日本語版

Cloudflareと
Workers
基礎から、実践まで。

作りたいWebサービスを、
小さく作って、公開してみる。

Cloudflareを使うと、何が変わる? AWSやGoogle Cloudとはどう選び分ける? 選ぶ理由を知り、自分のサービスを動かすところまで、図解と実習で学びます。

全21章公式情報確認 2026.09.17オフラインで閲覧可能
Workersを中心としたアプリ構成ブラウザからのリクエストをWorkersが受け、必要に応じてデータ保存、非同期処理、AIに接続し、応答を返す概念図。ブラウザリクエスト ↑↓ レスポンスYOUR APPLICATIONWorkers入力を受け取り、処理し、結果を返すデータ保存非同期処理AIKV · D1 · R2 · DOQueues · CronWorkers AI · Gateway

この教材で学ぶ全体像。必要なサービスを、必要な場面で追加します。

CHAPTER 01はじめに

小さなWebサービスを、自分で公開できるようになる

「イベントの申込みを受け付けたい」「自分の仕事に合うAIツールを作りたい」「作ったアプリを、ほかの人にも使ってもらいたい」。Cloudflareを学ぶと、こうしたアイデアを実際に使えるWebサービスにする方法が分かります。

画面を作るだけならできそうでも、公開するサーバー、データの保存先、アクセスが増えたときの対応まで考えると、急に難しく感じるかもしれません。Cloudflare、とくにWorkersの魅力は、小さなWebサービスに必要な機能を、一つずつ追加しながら始められることです。

最初の目標は、短いプログラムを書いて、アクセスすると結果が返るURLを一つ持つこと。その次に入力を受け取り、データを保存し、画面を付ける。Cloudflareの機能をすべて知ってから作り始める必要はありません。

この教材を読むことで目指す変化:「こんなサービスがあったら便利だ」と思ったときに、必要な機能を考え、小さく作って試せるようになることです。Cloudflareは、そのための有力な選択肢です。

たとえば、こんなものから始められる

イベント・コミュニティー

自分の申込み受付を作る

案内ページから送られた名前や参加区分を保存し、確認結果を返す。慣れたら定員確認や管理画面を追加できます。

最初に学ぶこと:入力の受付と保存。実運用では認証や個人情報の管理も必要です。

仕事・個人の道具

用途を絞ったAIツールを作る

入力した文章を決まった形式に整理する、よく使う説明文の下書きを作る。自分の用途に合わせた画面と処理を作れます。

最初に学ぶこと:画面とAIの接続。AIの利用料金や送信する情報も管理します。

作品・情報の公開

画像や資料を配信する

作品紹介ページに画像を載せる、ダウンロード資料を配る。保存先と配信の仕組みを知ると、公開する量が増えたときにも選択肢が広がります。

最初に学ぶこと:静的ファイルの配信とR2。保存量・操作数は費用に影響します。

既存システムの改善

今あるサイトに機能を加える

特定のURLだけ別の処理にする、公開データをキャッシュする、外部サービスからの通知を受け取る。サイト全体の作り直しを伴わない使い方もできます。

最初に学ぶこと:URLの振り分けと、既存サーバーとの接続。

これらは製品の機能を組み合わせた制作例です。完成済みのサービスが自動的に手に入るわけではなく、必要な処理や権限を実装していきます。

Cloudflareを選ぶと、何が変わる?

1. 最初の公開までに、自分で用意するものを少なくできる

Workersでは、自分でサーバーを借りてOSを設定する工程を持たずに、コードを配置できます。最初は独自ドメインも不要です。まず一つ動かし、結果を見ながら学べるため、「準備を終えるまで成果が見えない」という負担を小さくできます。

画面用のHTMLや画像もWorkersのStatic Assetsで配信でき、必要になったらデータベースやファイル保存を追加できます。画面とAPIを同じプロジェクトで扱える構成は、少人数で開発する場合にも試す価値があります。

公式資料:最初のWorkerを作る手順 / Static Assets

2. 複数の地域への配信を、共通の基盤に任せられる

Cloudflareは分散したネットワークでWeb通信やWorkersを処理します。利用者が増えるたびに自分で各地のサーバーを設置する方法とは、準備の仕方が変わります。広い地域の利用者に届けたいWebページや、短い処理のAPIでは、この仕組みが役立ちます。

ただし、実際の速さは保存先や外部APIとの距離にも左右されます。「Cloudflareへ移せば必ず速くなる」とは限りません。どこへの通信が多いかを見て、小さい機能で測ることが大切です。

公式資料:Workersの実行モデル

3. 小さく試し、利用量に合わせて費用を考えられる

Workersには無料プランがあり、最初の学習や小規模な試作に使えます。ファイル保存のR2には、R2から直接インターネットへ送るデータの転送料が無料という特徴があります。画像や資料を広く配信するサービスでは、費用を見直す理由になり得ます。

無料枠には上限があり、R2も保存量や読み書き操作は課金対象です。AIやログも別に考えます。比較するときは月額の表示だけでなく、自分のサービスの使われ方で、総額がどう変わるかを確認します。

公式資料:Workers料金 / R2料金

特に試してみる価値がある人:これから小さなWebサービスを作る人、少人数で画面とAPIを開発する人、公開ファイルの配信費用を見直したい人、既存サイトに一つ機能を足したい人。続いて、AIエージェントとの関係と、ほかのクラウドも含めた選び方を見ていきます。
先頭へ ↑
CHAPTER 02はじめに

なぜ今、AIエージェントの基盤として注目されるのか

AIに文章を書いてもらうだけでなく、資料を調べ、必要な処理を実行し、途中経過を保存して、仕事を先へ進めてもらう。そのようなAIエージェントを、自分のWebサービスとして提供するための選択肢として、Cloudflareの役割が広がっています。

たとえば、イベントの資料を受け取り、案内文を作り、人が内容を確認したら公開するサービス。AIモデルを呼ぶ機能に加えて、資料の保存、処理の再開、承認待ち、実行履歴の確認が必要です。Cloudflareには、これらを組み合わせるためのサービスがあります。Workersを学ぶと、AIへの一度の質問から、継続して使えるアプリへ進むための基本が身に付きます。

まず区別したい、二つの「AIで作る」

開発するとき

AIにアプリを作ってもらう

開発用AIがコードを書き、テストや公開手順を手伝います。完成するものは、普通の受付フォームやWebサイトでも構いません。公開を自動化するには、ツールの接続と適切な権限が必要です。

利用するとき

アプリの中でAIが作業する

利用者の依頼に応じて、AIがツールを選び、処理を繰り返します。こちらがAIエージェントを動かす仕組みです。会話の状態、実行権限、費用、途中で失敗した場合の扱いまで設計します。

二つを組み合わせることもできます。ただし、Cloudflareを選ぶだけで、AIが無条件に正しいアプリを作って公開してくれるわけではありません。AIが作った結果を自分で確かめられることが、学ぶ価値の一つです。

2026年の発表から分かること

時期公式に発表されたこと初心者にとっての意味
5月19日AnthropicのClaude Managed Agents向けにCloudflare Environmentsを提供する協業Claude側がエージェントの処理を進め、Cloudflare側がコードやツールを実行する環境などを提供する。AIモデルと、その作業を実行する環境は別の役割。
8月4日
Agents Week期間中
Cloudflare Agentsを発表エージェントを公開した後の、セッションや実行過程の観測・運用に重点が置かれている。
8月31日Bot ManagementのAdaptive Intelligenceを発表AIを動かす基盤に加えて、不正な自動アクセスへ対応する機能も拡充。発表時点では継続的な再学習が開始され、ほかの構成要素には今後の提供予定が含まれる。
9月3日Managed Defenseの脆弱性発見・修復支援を招待制の早期提供として発表OpenAI Daybreakモデルによる調査に、実際の通信・セキュリティ情報を組み合わせる。一般のWorkers無料機能や、無条件の自動修復とは異なる。

公式発表:Anthropicとの協業 / Cloudflare Agents / Adaptive Intelligence / 脆弱性発見・修復支援

Managed Defenseの発表では、GPT-5.6 Cyberを含むOpenAI Daybreakモデルを使用し、モデルの推論はOpenAI側で実行すると説明されています。修正案は検証と顧客のレビューを経る仕組みです。「Cloudflare上のAIが、すべての弱点を自動で直す」と受け取らないようにしましょう。

開発と運用、セキュリティという異なる分野で発表が続いたことは、Cloudflareを目にする機会が増える背景として考えられます。ただし、これは発表内容をもとにした見方です。個人の周囲で評判が広がった原因や、開発者全体の支持の割合を示す調査ではありません。

エージェントに必要な機能を、どう分担する?

依頼を受ける
Workers / 画面
考え、ツールを使う
AIモデル + 実行処理
保存・待機・再開
DO / R2 / Workflows
結果を確認する
観測 / 人による承認
資料から案内文を作るエージェントの構成例。すべての製品を最初から使う必要はありません。
役割主な選択肢何を担当するか
AIの応答を得るWorkers AI / 外部AI文章生成などの推論。AI Gatewayは呼び出しのログや制御を担う。
エージェントを実装するAgents SDK状態を持つエージェントを実装するSDK。Durable Objectsを利用する。
エージェントを観測・運用するCloudflare Agentsセッションやトレースを通じて、処理の経過や利用量を確認する。Agents SDKと同義ではない。
状態やファイルを残すDurable Objects / R2個々のエージェントの状態や、資料・成果物を保存する。
複数段階の処理を続けるWorkflows再試行、外部イベント待ち、人の承認待ちなどを含む処理を進める。
コードやブラウザを動かすSandbox / Browser Run / Dynamic Workers順に、隔離されたコンテナでの実行、実ブラウザの操作、実行時に渡されたコードの隔離実行。用途と制約が異なる。

公式資料:Agents SDK / トレースと観測 / AgentsとWorkflows / Sandbox / Browser Run / Dynamic Workers

隔離された実行環境でも、外部へ送ってよい情報や、実行してよい操作は別に決めます。公開・送信・削除には必要に応じて承認を設け、モデル呼び出し回数と処理時間にも上限を持たせます。トレースには入力内容や機密情報が残り得るため、記録する対象を選びます。製品ごとに料金と利用条件があり、すべてを無料で使えるわけではありません。

AIを使う側だけでなく、情報を公開する側にも関係がある

Cloudflareは、AIによるアクセスをSearch(検索)、Training(学習)、Agent(利用者に代わる取得・操作)に分けて管理する仕組みも提供しています。目的が違えば、サイト運営者が許可したい範囲も違うためです。

2026年9月15日の更新:新規ドメイン向けの推奨設定は、広告収益の有無で異なります。広告を使うサイトではSearchを許可、Trainingを「Disallow AI Training」、Agentを「広告のあるページでブロック」とする構成が示されています。広告を使わないサイトでは、各区分を許可する構成です。設定は変更できます。

「Disallow AI Training」は、学習への利用を拒否しつつ検索に残るための設定です。通信自体を止める「Block」とは異なり、対応するクローラーによる遵守が前提になります。検索と学習を兼ねるクローラーをBlockすると、検索にも影響します。古い発表だけを読んで「学習用は一律に遮断され、検索には影響しない」と判断しないでください。

最新の公式説明:2026年9月15日:検索とAI学習を区別する設定

話題になっていることと、自分に合うことを分けて考える

Cloudflareは以前からCDNやセキュリティで使われてきた会社です。最近の発表は、既存の実行・保存・通信の機能をエージェント開発へ広げる動きとして理解できます。株価やSNSの評判は関心の広がりを知る材料ですが、アプリが速くなること、安くなること、止まらないことの証明にはなりません。

これから作る人なら「AIで文章を整え、結果を保存する小さなアプリ」を試す。すでにAWSを使う人なら「新しいAI機能だけをWorkersで作り、既存DBと接続する」案を比較する。開発の手間、応答時間、総費用、復旧方法を自分の条件で確かめると、学習や移行の理由が具体的になります。

最初から自律的なエージェントを完成させる必要はありません。まずは入力を受け取り、結果を返すWorkerを一つ作る。保存とAI呼び出しを加え、その後に複数段階の処理へ進む。この順序なら、便利さを確かめながら、動く理由も理解できます。

先頭へ ↑
CHAPTER 03はじめに

AWS・Google Cloudと、どう選び分ける?

Cloudflareを選ぶ価値が高いのは、自分が作りたいものと、その仕組みが合うときです。Webサービスの作り始めや配信の改善では有力な候補ですが、既存のアプリや大量のデータを扱う仕事では、AWSやGoogle Cloudが向く場合もあります。

AWSのLambdaやGoogle CloudのCloud Runも、サーバーの管理をサービス側に任せてコードを実行できます。「サーバー管理が不要」という点だけでは、Cloudflareだけの優位性にはなりません。比較したいのは、公開・配信・保存まで含めて、自分の構成をどれだけ無理なく作れるかです。

公式資料:AWS Lambda / Google Cloud Runの実行環境

自分の目的から、候補を絞る

やりたいこと・今の状況検討しやすい選択その理由と、確認すること
小さなWebアプリやAPIを新しく作りたいCloudflare Workersコードの実行、静的ファイルの配信、保存先を段階的に組み合わせられる。実行時間・メモリ・使うライブラリが対応範囲か確認する。
画像やダウンロード資料の配信費用を見直したいCloudflare R2を比較候補にR2からの直接配信にはインターネット転送料がない。保存・操作・キャッシュの費用と、現在の契約条件を含めて比べる。
AWS上のDB・権限設定・社内ネットワークをすでに使っているAWS Lambda / ECS Fargateなどを継続する案既存の接続や運用経験を活かせる。移行のための接続・権限・監視の作り直しが、得られる効果に見合うか確認する。
既存のコンテナや、大きなメモリを使う処理を動かしたいGoogle Cloud Run / AWS ECS Fargateなどアプリと実行に必要なものをまとめた「コンテナ」を動かし、CPU・メモリを指定できる。起動方法、時間制限、永続保存の条件も確認する。
大量の履歴をSQLで集計・分析したいGoogle CloudのBigQueryなどの分析基盤大量データの分析用に設計されている。アプリのメモを保存するD1と、同じ役割だと考えない。
今のサービスは安定しており、明確な困り事がない現行基盤を使い、新機能だけCloudflareで試す案移行の作業とリスクを抑えながら、開発のしやすさを比較できる。

この表は各社の公式仕様をもとにした、教材としての選び方の提案です。速度・費用の実測比較や、すべてのサービスを網羅した順位表ではありません。

比較の根拠:AWS内でのLambdaとRDSの接続 / Fargateの実行条件 / Cloud Runのメモリ設定 / BigQueryの用途

Cloudflareの、不便になり得るところも知っておく

既存のプログラムを、そのまま動かせるとは限りません。通常のWorkersにはメモリやCPU時間などの制約があり、Node.jsとの互換性にも範囲があります。OSの機能に強く依存する処理や、長時間の重い計算は、別の実行方法を検討します。CloudflareにもContainersという別サービスがありますが、この教材の通常のWorkersとは実行条件・料金を分けて考えます。

データを置く場所の設計は必要です。Cloudflare側のAPIから、遠くのAWS上のデータベースへ何度も問い合わせれば、その通信が遅さの原因になることがあります。また、D1は既存のPostgreSQLやMySQLの完全な代替ではありません。既存DBを残して接続する方法も含めて判断します。

Cloudflare特有の機能を使うほど、移行時に直す部分は増えます。KVやDurable Objectsなどを使ったコードやデータ構造は、別のクラウドへそのまま移せるとは限りません。独自機能で開発が楽になる効果と、将来の変更に必要な作業の両方を考えます。

障害対応や費用管理の仕事は残ります。サーバーを直接管理しなくても、エラーの調査、データの復旧、利用者の権限、請求の確認は必要です。会社で採用するなら、監査・データの取扱地域・サポート契約なども条件に入れます。

公式資料:Workersの制限 / Node.js互換性 / Cloudflare Containers / 保存先の選び方

大規模障害から考える、一社への依存

2025年11月18日、Cloudflareでは中核の通信配信に大きな障害が発生しました。公式報告によると、攻撃ではなく、Bot Management用のファイル生成に関わる不具合が原因です。世界に分散した基盤でも、共通の仕組みの変更が広く影響することがあります。

個人の試作では、コードを手元にも保存し、重要なデータを取り出せるようにするところから始めます。仕事で使うなら、許容できる停止時間、バックアップの復元手順、別経路での障害案内を決めます。複数クラウドで動かす方法は費用と運用の複雑さも増すため、必要性に合わせて選びます。「障害後も話題だから安心」とは判断せず、便利さと停止時の影響を両方評価しましょう。

公式報告:2025年11月18日のCloudflareの障害

AWSからの乗り換えは、一つの機能で確かめられる

たとえば、既存アプリのDBはAWSに残し、新しい公開APIだけWorkersで試す。画像配信だけR2を比較する。既存サイトの手前で、特定のURLの処理やキャッシュだけをCloudflareに任せる。こうした部分的な採用から、移行する価値を確かめられます。

今の環境
AWS / Google Cloud
一つだけ試す
新しいAPI / ファイル配信
効果を比べる
手間 / 速度 / 総費用
合う範囲を採用
併用も、段階移行も
一度に移し替えず、採用する理由を確認しながら範囲を広げる進め方です。

Workersから既存のPostgreSQLやMySQLへ接続するために、Hyperdriveを使う選択肢もあります。一方、クラウドをまたぐ通信には、接続方法、権限、転送料、障害の調査範囲が増えるという面もあります。S3からR2を検討するなら、使用中のS3 APIが対応しているかも確認します。

公式資料:既存DBを活かすHyperdrive / R2のS3 API互換範囲

最初に試すなら、「小さくて、結果が分かるもの」

これから学ぶ人は、名前を送ると挨拶を返すURLを一つ作ってみてください。すでにAWSなどを使っている人は、公開してよいデータを返す小さなAPIを一つ作り、今の方法と比べてみてください。作成と更新にどれくらい手間がかかるか、どこまで自分で理解して扱えるかが見えてきます。

まずは、一つのURLを動かすところから。その経験があれば、Cloudflareの説明を読むだけでなく、自分の用途に合うかを判断できるようになります。この教材では、その最初の一歩から、保存・公開・運用までを順番に試していきます。

Hello Worldの実習へ進む → Webの仕組みから知りたい方は、このまま順に読み進めてください。

先頭へ ↑
CHAPTER 04基礎

何ができる? この教材の読み方

Cloudflare Workersを使うと、自分のプログラムをインターネット上で動かせます。たとえば、問い合わせを受け付けるAPI、画像を保存するサービス、AIへの質問を処理するアプリを作れます。

この教材では「Webの仕組みを知らない」状態から始め、短いプログラムを動かし、データ保存・公開・運用へ進みます。すべてのAPIを暗記する必要はありません。どこでコードが動き、何を保存し、何に料金がかかるかを説明できることが最初の目標です。

理解する

Webの仕組みとWorkers

DNS、CDN、HTTP、サーバーの意味から学びます。

動かす

最初のAPIを作る

文字を返すところから、URLやJSONを扱うコードへ進みます。

組み立てる

保存と運用を考える

データの種類に合わせて製品を選び、認証や料金を確認します。

初回は、この順に読んでください

  1. 全体像〜Workersの仕組み:図と太字を中心に読み、通信の流れをつかむ。
  2. Hello World〜環境変数:手元のパソコンでコードを変え、結果を確かめる。
  3. 保存・非同期・AI:まず比較表を読み、必要な製品を一つだけ試す。
  4. デプロイ〜実践:小さなアプリを完成させ、公開前の条件を確認する。
このファイルだけで読めます。図・スタイル・学習用の操作は内蔵されています。公式リンクを開く操作、開発ツールの導入、Cloudflareへの公開にはインターネット接続が必要です。教材内のシミュレーターは説明用で、Cloudflareに通信しません。

コードはJavaScriptを基本とし、設定にはコメントを書けるJSON形式のJSONCを使います。「ファイル全体」と書いた例は置き換え用、「断片」と書いた例は既存コードへの追加用です。実際に入力する値が必要な箇所には説明を添えます。

プログラミング経験がなくても進められますか?

はい。ただし最初はコードを一度に理解しようとせず、文字列を一つ変えて結果を確認してください。変数・関数・条件分岐を簡単に説明してから使います。自分で機能を増やす段階ではJavaScriptの基礎を並行して学ぶと理解が深まります。

先頭へ ↑
CHAPTER 05基礎

Cloudflare全体を、通信とアプリの両方から見る

Cloudflareは、Web通信の配信・保護と、アプリを動かすためのサービスを提供しています。Workersは、その中の「プログラムを実行する」サービスです。

ブラウザはWebページを見るアプリです。サーバーはブラウザなどから依頼を受け、データを返すプログラムやコンピューターを指します。元のWebサイトを動かしているサーバーをオリジンサーバーと呼びます。

利用者のブラウザ
ページを要求
Cloudflare
配信・保護・コード実行
必要なときだけ
既存サーバー / DB / API
図1:Cloudflare経由の通信の概念図。Workers自身が応答を作る構成では、既存サーバーは不要です。
領域主な製品・機能何をする?
名前を解決するDNSドメイン名から接続先を調べられるようにする。
配信を速くするCDN / Cache保存済みのコンテンツを再利用し、元サーバーへのアクセスを減らす。
通信を保護するDDoS対策 / WAF / TLS攻撃の緩和、リクエストの検査、通信の暗号化を行う。
アプリを動かすWorkers / Static Assets動的な処理とHTML・CSS・画像の配信を行う。
データを保持するKV / D1 / R2 / Durable Objects用途に合った方法でデータや状態を保存する。
処理をつなぐQueues / Cron Triggers後で行う処理や、時刻に合わせた処理を起動する。
AIを利用するWorkers AI / AI GatewayAIモデルの実行、またはAIへの呼び出しの管理を行う。

フロントエンドとバックエンド

フロントエンドは利用者が操作する画面、バックエンドはデータ保存や権限確認などを行うサーバー側の処理です。ブラウザに渡したJavaScriptは利用者から見えます。APIキーや管理者権限が必要な処理は、Workersなどのバックエンドで扱います。

APIはプログラム同士がデータや処理をやり取りするための決められた窓口です。「今日の予定を返すURL」「登録データを受け取るURL」などを作れます。Workersでは画面用HTMLもAPIのデータも返せます。

独自ドメインは、最初の実験には不要です。Workersには workers.dev のURLを使う方法があります。ドメイン購入や、既存サイトのDNS変更をしなくても学習を始められます。

公式資料:Workersと公開URL

公式資料:静的ファイルも配信できるStatic Assets

先頭へ ↑
CHAPTER 06基礎

DNS・CDN・セキュリティを順に理解する

DNS:ドメイン名から接続先を調べる

www.example.com のような名前がドメイン名です。通信先の識別に使うIPアドレスとの対応をDNSに登録します。AレコードはIPv4、AAAAはIPv6、CNAMEは別のホスト名、MXはメール配送先、TXTは所有権確認などの文字情報に使います。

ドメインを購入することと、DNSを管理することは別の作業です。CloudflareでDNS全体を管理する一般的な方法では、ドメイン登録事業者の画面でネームサーバーを指定します。既存サイトやメールがある場合は、その前に必要なDNSレコードをそろえます。

Proxied:オレンジの雲

Web通信がCloudflareを通ります。そこでキャッシュや対応する保護機能を適用できます。

DNS only:灰色の雲

Cloudflareは名前の問い合わせに答えますが、Web通信は原則として接続先へ直接向かいます。

プロキシ化できるのは対応するA・AAAA・CNAMEレコードです。MXやTXTまでオレンジの雲にするわけではありません。所有権確認用CNAMEなども用途に従って設定します。DNSをCloudflareに移しただけで、すべての通信が自動的に保護対象になるとは限りません。

公式資料:DNSのProxy status

CDN:同じ内容を何度も取りに行かない

CDNは複数の拠点からコンテンツを配信する仕組みです。キャッシュは、取得した内容を保存して次のリクエストに再利用することです。保存済みの内容を使えればHIT、使えず取得が必要ならMISSと呼びます。再利用できる期間はTTLで指定します。

1回目:画像を要求
MISS → 元サーバーから取得
キャッシュへ保存
2回目:同じ画像を要求
HIT → 保存済み画像を返す
元サーバーへの通信を省く
図2:キャッシュが有効で、同じキャッシュ拠点に到達した場合の簡略例。

通常のCDNはHTMLやJSONをデフォルトではキャッシュしません。ファイル拡張子、レスポンスヘッダー、ルールなどで動作が変わります。ログイン中の個人情報を含むページを共有キャッシュに入れると、他の人に見せてしまう可能性があります。

保存する場所を混同しない:ブラウザのキャッシュ、CloudflareのCDN、Workerが使うキャッシュは別のものです。「更新したのに変わらない」ときは、どの層が古い内容を返しているかを確認します。

公式資料:CDNの既定のキャッシュ動作

セキュリティ:それぞれ守る対象が異なる

仕組み役割アプリ側に残る仕事
TLS / HTTPS通信を暗号化し、接続先を検証する。誰に何を見せるかの判断。
DDoS対策大量の攻撃通信によるサービス妨害を緩和する。高コスト処理や利用者単位の使用量の制御。
WAFWebリクエストをルールで検査し、攻撃を遮断・緩和する。入力検証、SQLの安全な実行、所有者確認。
認証・認可本人確認と、許される操作の判定。アプリに合った設計と、各APIでの検証。

既存オリジンを使う構成では、ブラウザ→CloudflareとCloudflare→オリジンの両区間を考えます。Full (strict)は後半のTLS証明書も検証するモードで、オリジン側に有効な証明書などの条件が必要です。これは独自のオリジンに接続する場合の設定です。

公式資料:WAF

公式資料:DDoS Protection

公式資料:Full (strict)の条件

先頭へ ↑
CHAPTER 07基礎

Workersは、イベントが来るとコードを実行する

Workerには「HTTPリクエストを受け取ったら何をするか」を書きます。Cloudflareが実行環境を管理するため、自分で常時稼働するサーバーを用意する必要はありません。

サーバーレスは、サーバーが存在しないという意味ではありません。開発者がOS更新や台数管理を直接行わず、サービス側の実行基盤に処理を任せる方式です。コード、データ、権限、エラー、料金の管理は開発者の仕事です。

イベント
HTTP / 時刻 / キュー
対応するハンドラー
fetch / scheduled / queue
応答・保存・後続処理
図3:ハンドラーは、イベントが起きたときに呼ばれる関数です。

V8 Isolatesと、保存してはいけない状態

JavaScript版Workersの実行環境は、V8のIsolateという分離された実行領域を使います。各処理のために新しい仮想マシンを起動する方式とは異なり、素早く起動できるよう設計されています。ただし、常に同じ実行領域が残る保証はありません。

たとえばコードの先頭に let count = 0 と書いても、世界中で共有される永続的なアクセス数にはなりません。別の実行領域では値が違い、再起動で失われることもあります。残したいデータは保存サービスへ、利用者ごとの一時変数はリクエスト内へ置きます。

公式資料:Workersの実行モデル

「近くで動く」と「全処理が近くで完結する」は別

Cloudflareは分散したネットワークでリクエストを処理します。それでも、Workerから遠くのデータベースへ毎回問い合わせれば通信時間がかかります。利用者との距離だけでなく、データとの距離、問い合わせ回数、返す量も速さに影響します。特定の国や拠点で必ず実行されると決めつけないでください。

CPU時間と待ち時間

この例の経過時間は205msですが、CPU時間は5msです。CPU時間は、コードの実行にCPUを使った時間です。通信待ちが長い処理と、大きな配列の計算を続ける処理では、同じ経過時間でも消費が異なります。数値は理解のための例です。

Node.js用コードを使うとき

WorkersはNode.jsそのものではなく、Workersランタイムで動きます。Node.js互換APIはありますが、すべての機能が使えるわけではありません。現在の公式資料では compatibility_date2026-08-04以降ならNode.js互換機能が既定で有効です。古い日付のプロジェクトでは設定が異なります。読み込めても実行できないAPIもあるため、依存ライブラリの使用部分を確認します。

公式資料:Node.js compatibility:日付による違い

公式資料:CPU時間などの制限

先頭へ ↑
CHAPTER 08実習

Hello World:まず一つ、動くものを作る

最初はパソコンの中で動かし、返す文字を変えてみましょう。公開は後の章で行います。

1. 準備するもの

Cloudflareアカウント、対応するNode.js、コードを書くエディター、ターミナルを用意します。Macなら「ターミナル」アプリにコマンドを入力できます。コマンドはコンピューターに実行させる文字の指示です。

Node.jsにはnpmというパッケージ管理ツールが付属します。開発用ツールを動かすためにNode.jsを使いますが、Worker本体はWorkersランタイムで実行されます。Node.jsは公式サイトのサポート中のLTSを選び、Wranglerの現行要件も確認してください。

ターミナル:導入確認
node --version
npm --version

両方でバージョンが表示されれば準備を確認できます。command not found は、そのコマンドが見つからない状態です。導入後にターミナルを開き直し、再確認します。

公式資料:Wranglerの対応環境

2. プロジェクトを作る

ターミナル:新規作成
npm create cloudflare@latest -- my-first-worker
cd my-first-worker

npm create が作成ツールを実行し、cd が作業フォルダーを移動します。作成時の選択は Hello World example → Worker only → JavaScript を基本にします。Gitを使うかは任意、最初のデプロイは No にします。対話画面の名称は更新で変わることがあります。

ファイル役割
src/index.js実際に実行するWorkerのコード。
wrangler.jsonc名前、入口ファイル、互換日付、接続サービスの設定。
package.json開発ツールなどの依存関係。

3. コードを入れる

src/index.js を次の内容に置き換えます。

src/index.js:ファイル全体
export default {
  async fetch(request, env, ctx) {
    return new Response("こんにちは、Workers!", {
      headers: { "Content-Type": "text/plain; charset=utf-8" }
    });
  }
};

4. ローカルで起動する

ターミナル:起動したままにする
npx wrangler dev

表示されたローカルURL(通常は http://localhost:8787)をブラウザで開きます。上の例なら「こんにちは、Workers!」が返る想定です。文字を変えて保存し、ページを再読み込みします。終了するときはターミナルで Control + C を押します。

ここでの成功条件:表示されたことに加え、自分で文字を変え、その変更が反映されることを確かめます。localhost は自分のパソコンを指します。この段階では世界に公開されていません。

公式資料:公式CLI入門

コードを一行ずつ読む

記述意味
export defaultこのファイルから、Workersが使うハンドラーを提供する。
async fetch(...)HTTPリクエストが来たときに呼ばれる関数。asyncは非同期処理を扱う宣言。
request届いたURL、メソッド、ヘッダー、本文など。
env設定値や接続した保存サービスなど。
ctx処理の実行に関する補助機能。
return new Response(...)呼び出し元に返す応答を作る。
async / awaitとは?

外部APIや保存処理の完了を待つとき、await を使います。結果がまだない状態を表すPromiseから、完了後の値を受け取れます。async 関数ではawaitを使えます。「待つ間ずっとCPUで計算を続ける」という意味ではありません。

先頭へ ↑
CHAPTER 09実習

Request / Response:Webのやり取りを読む

Webのやり取りは「リクエストを送る → レスポンスを返す」が基本です。Workersでは、その両方をコードで扱えます。

Request:何をしてほしい?

URL:どの場所か
Method:何をするか
Headers:形式や認証などの付加情報
Body:送るデータ

Response:結果はどうだった?

Status:成功・失敗を表す番号
Headers:返す形式やキャッシュ方針
Body:HTML、JSON、画像など

URLの構成
https://api.example.com/api/hello?name=Hiro
└ 接続方式 ┘└ ホスト名 ┘└ パス ┘└ クエリ ┘

GETは取得、POSTは送信・作成、PUTPATCHは更新、DELETEは削除に使うのが一般的です。GETでページを開いただけでデータを消すような設計は避けます。

番号意味
200 / 201成功 / 作成成功一覧が取得できた / 登録できた。
400入力が不適切必要な項目がない。
401 / 403有効な認証がない / 操作が許可されないログインが必要 / 他人のデータは編集不可。
404 / 405対象なし / メソッド不許可URLが違う / POST専用へGETした。
429利用回数が多すぎる短時間の集中アクセス。
500 / 502内部エラー / 上流との通信などの問題コードの例外 / 依存APIが失敗。

名前に応じたJSONを返す

JSON{ "name": "Hiro" } のようにデータを表す形式です。次のコードでHello Worldを置き換え、/api/hello?name=Hiro を開いてください。

src/index.js:ファイル全体
export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (url.pathname === "/api/hello") {
      if (request.method !== "GET") {
        return new Response("GETを使ってください", {
          status: 405, headers: { Allow: "GET" }
        });
      }
      const name = url.searchParams.get("name") || "ゲスト";
      if (name.length > 40) {
        return Response.json({ error: "名前は40文字以内です" }, {
          status: 400
        });
      }
      return Response.json({ message: `こんにちは、${name}さん!` }, {
        headers: { "Cache-Control": "no-store" }
      });
    }

    return new Response("ページが見つかりません", { status: 404 });
  }
};

const は値に名前を付ける宣言、if は条件分岐です。new URL(...) でURLを分解し、pathname でパス、searchParams.get(...) でクエリ値を取り出します。|| の右側は、ここでは名前が空か未指定のときに使う値です。

通信しない学習用デモ

入力と応答の関係を試す

このファイル内で上の分岐を再現しています。実際のWorkerの稼働確認には、ローカルURLや公開URLを使ってください。

公式資料:Request API

公式資料:Response API

POSTの本文を読む

fetchハンドラー内の断片
const data = await request.json();
// 例:data.title が送信されたタイトル
// 形式だけでなく型・長さ・必要な項目も検証する

request.json() は、本文が不正なJSONなら例外になります。try / catch で扱い、400などを返します。本文は基本的に一度読むと消費されます。複数回読む設計や、大きなファイルを丸ごとメモリに載せる設計は避けます。後の実習では、小さいJSONに限定して扱います。

先頭へ ↑
CHAPTER 10基礎

ルーティングは、公開先とコード内の2段階

まず「どのWorkerへ届けるか」をCloudflare側で決め、その後「Worker内のどの処理を行うか」をパスやメソッドで決めます。

api.example.com/items
公開先の設定
Workerを選ぶ
コード内の分岐
GET /items を処理
図4:ドメインの接続と、アプリ内のURL分岐は別々の設定です。
公開方法向く場面重要な条件
workers.dev最初の実験、個人・趣味のプロジェクト。独自ドメインなしで始められる。本番の重要用途では公式はRouteかCustom Domainを推奨。
Custom DomainWorker自体がサイトやAPIの応答を作る。自分のCloudflare上の有効なゾーンが必要。ホスト名全体をWorkerへ接続する。
Route既存Webサーバーの前で処理を加える。有効なゾーンと、対象ホストのプロキシ化されたDNSレコードが必要。

ゾーンはCloudflareで管理するドメインの設定単位です。Custom DomainではCloudflareがDNSと証明書を設定します。RouteではURLパターンを指定します。次の2例は用途が異なるので、必要な方だけを設定へ追加します。

wrangler.jsoncのプロパティ断片:Workerが応答を作る
"routes": [
  { "pattern": "api.example.com", "custom_domain": true }
]
wrangler.jsoncのプロパティ断片:既存サイトの前に配置
"routes": [
  { "pattern": "www.example.com/api/*", "zone_name": "example.com" }
]

example.com は説明用ドメインです。自分の管理するドメインへ置き換えます。Custom Domainはホスト名単位なので、/items などの振り分けはコード側で行います。既存CNAMEと競合するなど、追加できない条件もあります。

既存サーバーの応答にヘッダーを追加する例

次は既存オリジンの前のRoute用です。fetch(request) で元サーバーに問い合わせます。ハンドラー名のfetchと、外向き通信のfetchは役割が異なります。

Route用:src/index.js全体
export default {
  async fetch(request) {
    const upstream = await fetch(request);
    const response = new Response(upstream.body, upstream);
    response.headers.set("X-App-Version", "1");
    return response;
  }
};

この例を、転送先がないCustom Domain構成にそのまま使わないでください。外部APIへ送る場合は、転送先URLと送信ヘッダーを明示します。

公式資料:公開先の選び方

公式資料:Custom Domains

公式資料:Routesの設定条件

先頭へ ↑
CHAPTER 11実習

環境変数・Secrets・Bindingsを使い分ける

コードに埋め込む必要のない値や接続先を、設定で渡します。envからアクセスできても、その種類と扱いは異なります。

種類入れるものコードからの使い方
環境変数(vars)アプリ名、非機密の設定値。env.APP_NAME
SecretsAPIキー、機密トークン。env.EXTERNAL_API_KEY
BindingsD1やKVなど、Workerに接続したサービス。env.DB.prepare(...) など。

Bindingはコード上の名前とリソースを接続する設定です。DBという名前は自動で生えるものではありません。設定に登録した名前とコードで使う名前を合わせます。varsやSecretsも、広い意味ではWorkerへ値を渡すBindingです。

基本の設定ファイル

wrangler.jsonc:基本例
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-first-worker",
  "main": "src/index.js",
  "compatibility_date": "2026-09-17",
  "vars": { "APP_NAME": "はじめてのWorkers" },
  "observability": { "enabled": true }
}

compatibility_date はランタイムの互換動作の基準日です。デプロイ日を記録する欄ではありません。更新すると有効になる動作が変わることがあるため、既存アプリではテストしてから更新します。サンプルは教材確認日を使っています。

公式資料:互換日付の考え方

秘密は、ローカルと公開環境に別々に登録する

ローカル開発では、設定ファイルと同じ場所に .dev.vars を作ります。以下の値はダミーです。ブラウザへ送るHTMLやJavaScriptに書かないでください。

.dev.vars:ローカル用
EXTERNAL_API_KEY="local-test-value"
.gitignoreに追加
.dev.vars*
.env*

公開環境への登録は次のコマンドで行い、対話入力欄に値を入力します。コマンドの引数に秘密そのものを記載する必要はありません。

ターミナル:公開環境のSecretを登録
npx wrangler secret put EXTERNAL_API_KEY
このコマンドは公開環境を変更します。wrangler secret put は新しいWorkerバージョンを作り、直ちにデプロイします。すでに運用中なら変更のタイミングを考えます。ローカルの .dev.vars は自動アップロードされません。

Secretsでも、コードがレスポンスやログに出力すれば漏れます。console.log(env) や、秘密入りのエラーメッセージを返す処理は書かないでください。

公式資料:Secretsの登録・ローカル開発

開発・検証・本番を分ける

検証用の環境を staging、実利用の環境を production と呼ぶことがあります。Wranglerの環境設定を使えば、同じコードを異なるリソースに接続できます。varsやBindingsは環境ごとに必要な設定を定義し、Secretsも対象環境へ登録します。検証中に本番データを書き換えない接続先にすることが重要です。

公式資料:環境変数と環境ごとの設定

先頭へ ↑
CHAPTER 12応用

データをどこに置くかは、「どう読み、どう更新したいか」で決める

Cloudflareには保存先がいくつもあります。まず「設定を世界中で速く読みたい」「SQLで検索したい」「ファイルを置きたい」「同じ状態を順番に更新したい」のどれかを選びます。保存するデータの形より、読み書きの性質から選ぶと迷いません。

SQLはデータベースに検索や更新を指示する言語です。SQLiteはD1などが使うデータベース技術。namespaceはKVのデータを分ける単位、bucketはR2の保存単位です。以下の各例は独立した練習です。Hello Worldと同じ手順で別々のWorkerプロジェクトを作り、設定断片を基本のwrangler.jsoncへ追加してください。作成コマンドはCloudflare側にリソースを作りますが、通常のローカル開発では保存データをローカルに分けて扱います。

設定・キャッシュ
KV
表形式のデータ
D1
画像・動画・添付
R2
順番と共有状態
Durable Objects

KV: 読み込みの多い設定とキャッシュ

Workers KVは、キーに対して値を保存するグローバルなストアです。例えば site:theme にサイト設定を、user:42:locale に言語設定を置けます。世界中の拠点でキャッシュされるため、同じ値を何度も読む用途に向きます。

具体例: 管理画面で「今週の告知」を更新し、閲覧ページではその文章を読むだけにする。外部APIの結果を数分だけ保存し、毎回APIを呼ばないようにする。

選ばない場面: 書込み直後に、全地域の利用者が必ず新しい値を読む必要がある場面です。KVは結果整合性であり、他地域のキャッシュでは古い値や「まだ存在しない」という結果が60秒以上残ることがあります。残数、予約、投票数のような競合する更新には向きません。

以下はローカル実習用で、認証なしの最小例です。公開すると誰でも告知を変更できるため、そのまま本番へ出してはいけません。

// 単独例: POSTで書き、GETで読む
export default {
  async fetch(request, env) {
    if (request.method === "POST") {
      await env.SETTINGS.put("announcement", "10月のイベントを公開しました");
      return new Response("saved");
    }
    if (request.method !== "GET") return new Response("Method Not Allowed", { status: 405, headers: { Allow: "GET, POST" } });
    const message = await env.SETTINGS.get("announcement");
    return new Response(message ?? "お知らせはありません");
  }
};
# ターミナル:namespaceを作成
npx wrangler kv namespace create SETTINGS
// wrangler.jsonc の断片。出力されたidを設定する
{ "kv_namespaces": [{ "binding": "SETTINGS", "id": "<NAMESPACE_ID>" }] }

実行準備: 開発環境と本番環境は別namespaceに分けます。ローカルの wrangler dev は通常KVをローカルにシミュレートします。本番namespaceへ接続する設定では、書込みも実データに反映されます。

公式: KV概要 / 整合性とキャッシュの仕組み / 料金

D1: SQLで検索・集計するアプリのデータ

D1はSQLiteのSQLを使えるサーバーレスデータベースです。ユーザー、記事、コメント、申込みのように、列を持つデータを条件検索・結合・集計したいときに選びます。Workerからbinding経由で呼べるので、別のDB接続先を管理せずに始められます。

具体例: イベント申込みフォームで、メールアドレスと参加区分を保存する。管理画面では「参加区分がオンラインの人だけ」をSQLで検索する。

設計上の注意: 1つのD1の実行インスタンスではクエリを一度に1本ずつ処理します。読み取りレプリカを使う構成は別途考えます。アクセスが集中して遅いクエリが続くと、待ち行列が埋まり overloaded エラーになり得ます。検索条件に使う列へインデックスを作り、全件走査を避けます。無料枠は「クエリ回数」ではなく、読んだ行500万/日・書いた行10万/日で消費します。

// fetchハンドラー内の断片:D1に申込みを登録する
const result = await env.DB.prepare(
  "INSERT INTO registrations (email, attendance_type) VALUES (?1, ?2)"
).bind("hiro@example.com", "online").run();

return Response.json({ id: result.meta.last_row_id });
-- 事前に一度だけ実行するSQL(migrationファイルに保存)
CREATE TABLE registrations (
  id INTEGER PRIMARY KEY,
  email TEXT NOT NULL,
  attendance_type TEXT NOT NULL
);
CREATE INDEX idx_registrations_type ON registrations(attendance_type);

実行準備: wrangler d1 create app-db でDBを作り、設定ファイルの d1_databasesbinding: "DB"database_id を登録します。スキーマはmigrationファイルとして管理し、ローカルと本番へ同じ順で適用します。

公式: D1概要 / 上限・並行性 / 料金

R2: 画像、動画、添付ファイルをオブジェクトとして保存する

R2はS3互換のオブジェクトストレージです。写真、PDF、音声、動画、バックアップ、生成AIの出力のように、ひとまとまりのファイルを置く用途に合います。ファイルそのものをD1やKVへ押し込むのではなく、R2へ置いて、D1にはファイル名・所有者・公開状態などのメタデータを持たせるのが基本形です。

具体例: 利用者がアップロードしたプロフィール画像を avatars/42.jpg としてR2へ保存し、D1の users テーブルにはそのキーだけを保存する。

費用の注意: R2から直接インターネットへ出すegressは無料ですが、保存量と操作数には料金があります。頻繁に読まれる小さなファイルを大量に扱う場合は、Class B操作数も見積もります。Infrequent Accessは取得料と最低30日保存があり、無料枠の対象はStandardだけです。

以下はローカル実習用で、認証なし・本文サイズ制限なしの最小例です。小さいテキストだけで試し、このまま公開しないでください。この例は全体をメモリに読み込みます。大きいファイルには長さが分かるストリームやマルチパート処理などを検討します。実サービスではサイズ・形式を検証し、誰がどのキーを読み書きできるかをWorker内で認証・認可します。アップロードと配信を別Workerにすることもできますが、必須ではありません。

// 単独例: PUTで本文を保存し、GETで同じキーを読む
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const key = url.pathname.replace(/^\//, "") || "sample.txt";
    if (request.method === "GET") {
      const object = await env.FILES.get(key);
      return object ? new Response(object.body, {
        headers: { "Content-Type": "text/plain; charset=utf-8", "X-Content-Type-Options": "nosniff" }
      }) : new Response("Not Found", { status: 404 });
    }
    if (request.method !== "PUT") return new Response("Method Not Allowed", { status: 405 });
    // 小さいテキスト用。全文をメモリに読み込む。
    await env.FILES.put(key, await request.arrayBuffer(), {
      httpMetadata: { contentType: request.headers.get("content-type") ?? "text/plain" }
    });
    return Response.json({ key });
  }
};
# ターミナル:bucketを作成
npx wrangler r2 bucket create learning-files
// wrangler.jsonc の断片
{ "r2_buckets": [{ "binding": "FILES", "bucket_name": "learning-files" }] }

実行準備: DashboardでR2 subscriptionを有効にしてbucketを作成します。公開配信する場合も、必要な認可をWorkerへ実装します。ローカルではR2をシミュレートでき、remote bindingへ切り替えた場合の操作は実bucketのデータと料金に影響します。

公式: R2開始方法 / 料金と無料枠

Durable Objects: 1つの状態を、みんなで矛盾なく使う

Durable Object(DO)は、特定のIDに対応する1つのオブジェクトが計算と保存を担当する仕組みです。たとえば「チャットルーム room-a」「商品 SKU-123」「共同編集する文書 doc-9」のように、同じ状態へ複数人が同時に触れる場面で使います。各IDへの処理を集めるため、更新の順序を管理できます。

具体例: 先着10名の予約枠を減らす。通常のKVで remaining を読んでから書くと、同時アクセスで二重予約が起き得ます。予約対象ごとにDOへ依頼すれば、残枠の確認と減算を同じ場所で順番に扱えます。

DOでも、コードの組み方は重要です。外部APIをawaitしている間には別のリクエストが進む場合があります。下の例は、カウントの更新と取得の間に外部通信を挟まない同期SQLです。複数の変更を一まとまりにする場合は、トランザクションなどの仕組みも確認します。

公式:DOの並行処理とトランザクション

KVとの関係: 「世界中で素早く読む公開設定」はKV、「同じキーへの更新を競合なく決める」はDOです。DOで確定した結果をKVへ配る設計もありますが、KV側の読み取りは引き続き結果整合性です。

以下はローカル学習用の完全な最小例です。入口Workerはすべて同じ名前のObjectへPOSTを転送します。本番の予約やチャットでは、Object名の決め方と入口の認証・認可を設計します。この例には認証を実装していません。

// src/index.js: 入口WorkerとSQLite Durable Object
import { DurableObject } from "cloudflare:workers";

export class Counter extends DurableObject {
  constructor(ctx, env) {
    super(ctx, env);
    this.sql = ctx.storage.sql;
    this.sql.exec("CREATE TABLE IF NOT EXISTS state (key TEXT PRIMARY KEY, value INTEGER NOT NULL)");
    this.sql.exec("INSERT OR IGNORE INTO state (key, value) VALUES (?, ?)", "visits", 0);
  }

  async fetch(request) {
    if (request.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
    this.sql.exec("UPDATE state SET value = value + 1 WHERE key = ?", "visits");
    const row = this.sql.exec("SELECT value FROM state WHERE key = ?", "visits").one();
    return Response.json({ visits: row.value });
  }
}

export default {
  async fetch(request, env) {
    if (request.method !== "POST") return new Response("POST / で数える", { status: 405 });
    const id = env.COUNTER.idFromName("learning-counter");
    return env.COUNTER.get(id).fetch(request);
  }
};
// wrangler.jsonc: bindingとSQLite migrationを同じデプロイに含める
{
  "name": "learning-counter",
  "main": "src/index.js",
  "compatibility_date": "2026-09-17",
  "durable_objects": {
    "bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
  },
  "migrations": [{ "tag": "v1", "new_sqlite_classes": ["Counter"] }]
}

実行準備: Hello Worldと同じ手順でWorker onlyのJavaScriptプロジェクトを作成し、この2ファイルに置き換え、 npx wrangler dev で起動します。別のターミナルから curl -X POST http://localhost:8787/ を繰り返し、visitsが増えることを確認します。新規クラスはSQLiteバックエンドが推奨され、Freeで利用できるDOもSQLiteのみです。クラス名やmigrationタグを途中で不用意に変更すると、既存状態を意図どおり引き継げないため、リリース前にmigrationを確認します。

公式: Durable Objects概要 / 料金

先頭へ ↑
CHAPTER 13応用

待たせない処理と、決まった時刻の処理を分ける

利用者の画面をすぐ返したいとき、重い処理はQueuesへ渡します。毎日・毎時の処理はCron Triggersで起動します。どちらもWorkerを動かしますが、Queuesは「届いた仕事」、Cronは「時刻」がきっかけです。

Producerは仕事をキューへ送る側、Consumerは取り出して処理する側です。Dead Letter Queue(DLQ)は、指定回数の再試行後も失敗した仕事の送り先です。DLQを設定し、そこに届いた仕事を調査・復旧する手順も用意します。

フォーム送信
Worker
Queues
仕事を保管
Consumer Worker
後で実行
ctx.waitUntil()とQueuesは別の仕組みです。waitUntilは応答後にも短い処理を続ける補助機能で、HTTPでは応答送信や切断後、最大30秒まで延長できます。永続的な仕事の保管や自動再試行を保証するものではありません。失敗した仕事を残して再試行したい場合はQueuesなどを検討します。

公式:ContextとwaitUntil

Queues: 受け付けた処理を非同期に実行する

Queuesはメッセージを保存して非同期に処理するキューです。フォーム送信を受けたWorkerが「確認メールを送る」「画像を変換する」「外部サービスへ同期する」という仕事を積み、Consumer Workerが後で取り出します。最初のHTTP応答を外部APIの遅さから切り離せます。

具体例: 申込み完了画面はすぐ返し、メール配信だけをQueueへ送る。メールサービスが一時的に失敗しても、Consumerは再試行できます。何度も失敗するメッセージはDead Letter Queueへ送り、運用者が確認します。

設計上の注意: Consumerは少なくとも1回の配信を前提にします。同じメッセージが再試行で届いても二重メールや二重課金にならないよう、外部サービス側の冪等キーなどを使って処理を冪等にします。D1へIDを記録するだけでは、外部送信のexactly-onceを保証できません。1メッセージは128 KBまでです。通常の配信は書込み・読取り・削除の約3操作なので、無料枠は「メッセージ1万件/日」ではありません。

// src/index.js:ファイル全体。ローカル学習用・認証なし。
export default {
  async fetch(request, env) {
    if (request.method !== "POST") {
      return new Response("POSTを使ってください", {
        status: 405, headers: { Allow: "POST" }
      });
    }
    await env.MAIL_QUEUE.send({
      eventId: crypto.randomUUID(), task: "send-confirmation"
    });
    return new Response("queued", { status: 202 });
  },
  async queue(batch, env) {
    for (const message of batch.messages) {
      // 学習用のログ出力。メール送信は行わない。
      console.log("received", message.body.eventId, message.body.task);
      message.ack();
    }
  }
};
# ターミナル:QueueとDLQを作成する
npx wrangler queues create mail-jobs
npx wrangler queues create mail-jobs-dlq
// wrangler.jsoncへの追加設定:同じWorkerにproducer/consumerを置く
{
  "queues": {
    "producers": [{ "binding": "MAIL_QUEUE", "queue": "mail-jobs" }],
    "consumers": [{
      "queue": "mail-jobs", "max_batch_size": 10, "max_batch_timeout": 5,
      "max_retries": 3, "dead_letter_queue": "mail-jobs-dlq"
    }]
  }
}

実行準備: Queueを作成し、producer側は queues.producers、consumer側は queues.consumers を設定します。実サービスで外部メールAPIを呼ぶ部分は、相手サービスの冪等キー、失敗時の記録、DLQからの復旧手順を追加します。Freeは操作10,000/日、保持期間は固定24時間です。

公式: Queues開始方法 / 料金 / 上限

Cron Triggers: 決まった時刻にWorkerを起動する

Cron式は「分・時・日・月・曜日」の5項目で時刻の条件を表します。* は毎回を意味します。Cron Triggersはこの式でWorkerの scheduled() handlerを動かします。毎朝のニュース収集、毎時の古いデータ掃除、毎晩の集計、期限切れの通知などに使います。HTTPアクセスがなくてもWorkerを実行できるのが特徴です。

具体例: 日本時間の毎朝9時に前日分を集計したい場合、UTCで考えます。日本標準時はUTC+9なので、UTC 0時を指定する 0 0 * * * が毎日9時に当たります。夏時間を使う地域では時差変更も考慮します。

運用上の注意: CronはUTCで実行され、厳密な秒単位の実行保証ではありません。設定をWranglerで管理するWorkerでは、Dashboardと設定ファイルを混在させません。Wranglerのデプロイは指定したTrigger一覧で以前の設定を置換し、空配列 crons: [] はすべて削除します。

// 単独例: 毎日UTC 0:00(日本時間09:00)に動くWorker
export default {
  async scheduled(controller, env, ctx) {
    console.log("daily summary started", new Date().toISOString());
  }
};
// wrangler.jsonc の断片
{
  "triggers": {
    "crons": ["0 0 * * *"]
  }
}

実行準備: Workerに scheduled() を実装し、設定ファイルへcron式を追加してデプロイします。Freeはアカウントあたり5 Triggerまでで、WorkerのCPU上限も通常10 msです。重い処理はCronからQueuesへ仕事を積み、Consumerに分けると失敗時の再試行と時間管理がしやすくなります。

公式: Cron Triggers / Workers料金 / Workers上限

先頭へ ↑
CHAPTER 14応用

AIを実行するWorkers AIと、AI呼び出しを整えるAI Gateway

Workers AIはCloudflare上でモデルを推論するサービスです。AI Gatewayは、Cloudflareや外部AIプロバイダーへの呼び出しを記録・キャッシュ・制限する入口です。両者は競合せず、Workers AIをAI Gateway経由で呼ぶこともできます。

推論は学習済みモデルへ入力を渡して結果を得ることです。LLMは文章などを扱う大規模言語モデル、GPUは並列計算が得意な計算装置。埋め込みは文章などを数値の列へ変換し、意味の近さを比較しやすくする方法です。

アプリのWorker
AI Gateway
ログ・制御・キャッシュ
Workers AI または
外部AIプロバイダー

Workers AI: CloudflareのGPUでモデルを推論する

Workers AIでは、LLM、埋め込み、画像、音声などのモデルをサーバーレスGPUで実行します。Worker、Pages、Cloudflare APIから呼べるため、GPUサーバーの確保やスケールを自分で管理せずにAI機能を組み込めます。

具体例: 問い合わせ文を埋め込みモデルでベクトル化して検索に使う。短い要約を生成する。音声ファイルを文字起こしする。まず1つの入力と1つのモデルで試し、応答時間と出力品質を確かめてから画面に組み込みます。

費用と可用性の注意: 無料枠は「10,000 Neurons/日」です。Neuronはモデル別のGPU計算量で、リクエスト数ではありません。入出力の長さなどで消費量が変わります。Freeは日次枠を超えると利用が止まり、Paidでは超過分が従量課金されます。一部の計算負荷が高いモデルはFreeで利用できずPaidが必要です。利用前にモデルごとの入力・出力料金とライセンス条件を確認します。

// 単独例: Workers AI bindingでチャットモデルを呼ぶ
export default {
  async fetch(request, env) {
    const answer = await env.AI.run("@cf/meta/llama-3.2-1b-instruct", {
      messages: [
        { role: "system", content: "日本語で短く答えてください。" },
        { role: "user", content: "Cloudflare Workersとは何ですか?" }
      ],
      max_tokens: 120
    });
    return Response.json(answer);
  }
};

実行準備: 設定ファイルへ "ai": { "binding": "AI", "remote": true } を追加します。固定したモデルIDで開発を始め、実サービスでは入力長・出力長・日次Neuron利用量をDashboardで監視します。AIモデルはローカルにはシミュレートされず、wrangler dev からの推論もリモートで実行され、Neuronの利用枠を消費し、プランと使用量によって課金されます。max_tokens のように出力上限を置き、秘密情報をプロンプトへ直接入れません。

公式: Workers AI概要 / 例で使うモデルの仕様 / 料金とNeuron / ローカル開発とリモートAI / Paid必須モデルの告知

AI Gateway: AI呼び出しの記録、キャッシュ、制限を一か所に置く

AI Gatewayはモデルそのものを提供する代わりに、AIへのリクエストを通す入口です。OpenAI、Anthropic、Google AI Studio、Workers AIなどをまとめ、分析、永続ログ、キャッシュ、レート制限、認証、Unified Billingを適用できます。複数のAIを試すアプリや、利用量を把握したいチームに向きます。

具体例: 同じ質問が短時間に繰り返されるFAQではキャッシュを有効にし、AIへの重複呼び出しを減らす。ログからプロンプト、応答時間、失敗率を確認して改善する。利用者ごとの制限をしたい場合は、Gatewayのレート制限だけに頼らず、Worker側で利用者を認証して識別し、そのIDに基づく制限も実装します。

大事な区別: AI Gatewayのコア機能は無料でも、推論そのものが無料になるわけではありません。外部プロバイダーをUnified Billingで使う場合は、Cloudflareクレジットを購入し、購入額に5%手数料が加わります。GuardrailsはWorkers AIの推論として消費されます。ログに個人情報や機密文を残す設計は、保存方針を決めてから有効にします。

// fetchハンドラー内の断片:AI呼び出しへGatewayを追加する
const answer = await env.AI.run(
  "@cf/meta/llama-3.2-1b-instruct",
  { prompt: "Cloudflare Workersを1文で説明して", max_tokens: 80 },
  {
    gateway: {
      id: "learning-gateway", // Dashboardで作った同一アカウントのGateway名
      skipCache: false,
      cacheTtl: 300
    }
  }
);
return Response.json(answer);

実行準備: Workers AI bindingを設定し、DashboardでGatewayを作成してその名前を gateway.id に指定します。最初はテスト用Gatewayで、ログに残る内容とエラー時の振る舞いを確認します。Freeの永続ログは全Gateway合計10万件、作成できるGatewayは10個です。外部モデルをUnified Billingで呼ぶ場合は、クレジット残高と自動チャージ設定も確認します。

公式: Workers AIとの連携 / Gatewayを指定するbinding例 / AI Gateway料金 / 上限

確認したいこと 最初に見る場所
Cloudflareのモデルを自分のWorkerで動かしたい Workers AI。モデル別Neuron消費とFree利用可否を確認する。
OpenAIなど複数社の利用量を一か所で追いたい AI Gateway。ログの機密性、レート制限、課金経路を決める。
生成に時間がかかり画面を待たせたくない Workerで受付 → Queuesへ投入 → ConsumerからAIを呼ぶ。
毎朝のAI要約を作りたい Cron Triggerで起動し、長い処理はQueuesへ渡す。
先頭へ ↑
CHAPTER 15実習

デプロイ・デバッグ・ログで動作を確かめる

デプロイとは、コードや設定を実行環境へ配置することです。コマンドが成功した後も、公開URLで期待どおりに動くかを確認します。

手元で修正
ローカルで確認
公開環境へ配置
公開URL・ログを確認
図5:デプロイの成功と、アプリの動作確認は別の確認です。

最初の公開

Hello Worldや名前を返すAPIなど、公開してよい内容のWorkerで実行します。

ターミナル:ログインと公開
npx wrangler login
npx wrangler deploy

ログインではブラウザでCloudflareアカウントを認証します。公開後に表示されるURLを開いて確認してください。学習例では https://my-first-worker.<自分のサブドメイン>.workers.dev のような形式です。API例ならその末尾に /api/hello?name=Hiro を付けます。

確認試すこと
正常系正しいURL・メソッド・入力で、期待するデータが返る。
入力エラー長すぎる文字、欠けた項目、不正JSONを送っても安全に失敗する。
境界存在しないURLや許可しないメソッドに、適切な応答が返る。
本番接続本番のBindings・Secrets・データがそろっている。

公式資料:Wranglerでの公開手順

ログを見る

ターミナル:公開Workerのリアルタイムログ
npx wrangler tail
fetchハンドラー内の断片:機密情報を含めない
console.log({ event: "request", method: request.method,
  path: new URL(request.url).pathname });

保存して後から検索するWorkers Logsは、"observability": { "enabled": true } を設定し、再デプロイします。ダッシュボードの対象WorkerのObservabilityで確認できます。ローカルのログと公開環境のログを混同しないでください。

ログには保存期間と使用量の制約があります。サンプリングは記録するリクエストの割合を下げる機能です。全件を残しているとは限らないため、「ログがないから呼び出されていない」とは断定できません。トークン、本文全文、個人情報を安易に記録しない設計にします。

公式資料:Workers Logsの有効化と検索

公式資料:ログの種類

困ったときは、症状から調べる

症状まず確認する場所
ローカルURLが開かない起動中のターミナル、表示されたポート番号、停止していないか。
404URLのパス・大文字小文字と、コードの条件が一致しているか。
405ブラウザのGETでPOST専用のURLを開いていないか。
env.DBが未定義Binding名、選択した環境、設定ファイル。
no such tableD1のスキーマを、ローカル・リモートの正しい方に適用したか。
1102などの資源制限エラーCPUやメモリの使用量、大きなデータの読み込み。
ブラウザだけ失敗する開発者ツールのNetwork、CORS、Cookie、実際のステータス。
公開版だけ失敗する公開先のSecrets、Bindings、外部サービスの権限。

デバッガーでは途中で処理を止め、変数を調べられます。まず再現する入力を一つに絞り、ローカルのログやDevToolsで確認すると原因を追いやすくなります。

更新で壊れたときのために

ソースをGitで管理し、変更前の状態へ戻せるようにします。Workersのバージョン・デプロイ管理も利用できます。ただしコードを戻しても、データベースに行った変更や外部への送信は元に戻りません。DB変更は互換性と復旧方法を別に検討します。

先頭へ ↑
CHAPTER 16基礎

料金と制限:何を数えているかを理解する

Workersの料金は、主にリクエスト数とCPU時間で考えます。保存サービス、ログ、AIなどは、それぞれの使用量も確認します。

確認日:2026年9月17日。以下は公式ドキュメントで確認した通常のWorkers Free / Paid(Standard)の代表値です。金額は米ドル。税・為替・個別契約・他サービス料金は含みません。申し込み前にはリンク先で再確認してください。
項目FreePaid / Standard
基本料金$0アカウントあたり月額最低 $5
リクエスト1日100,000件月10,000,000件込み
超過100万件あたり $0.30
CPU時間呼び出しあたり10ms月30,000,000 CPU-ms込み
超過100万CPU-msあたり $0.02

Freeの日次リセットはUTCの0時です。日本時間では9時に相当します。Webサイト向けのPro / Businessと、Workers Paidは別のプランとして確認してください。

WORKERS STANDARD の概算

月間リクエストとCPU時間を変えてみる

全リクエストでコードが実行される前提。他サービス、キャッシュによるCPU削減、ログは含めない単純計算です。

初期値の例では、月2,000万回 × 5ms = 1億CPU-ms。基本 $5 + リクエスト超過 $3 + CPU超過 $1.40 = 月 $9.40です。これは見積もり例であり、実請求の保証ではありません。

通常のStatic Assetsへの直接のリクエストは無料・無制限です。ただしWorkers Cachingを有効にした場合は、キャッシュから返るリクエストも課金対象になります。キャッシュHITではWorkerのCPU実行は課金されません。構成による違いを確認してください。

公式資料:Workersの料金・キャッシュ課金の注記

無料枠と、実行上の制限は別

代表的な制限現在の値・読み方
メモリFree / Paidともに128MB。大きいファイルはストリーム処理を検討。
PaidのHTTPリクエストのCPU既定30秒。設定可能な上限は5分。Freeの10msとは別。
同時に開く外向き接続1リクエストあたり6。外部サービスの応答本文の扱いにも注意。
Subrequest外向きfetchなど。既定でFree 50 / Paid 10,000回(1リクエストあたり)。
受信本文のサイズWorkersのプランではなくCloudflare側のプランにも依存。Free / Proでは100MB。

HTTPの経過時間とCPU時間の制限は異なります。CronやQueueには別の実行条件があるため、HTTPの上限をそのまま当てはめません。大きな本文を受け付けられても、全体をメモリに読み込めるとは限りません。

公式資料:最新の制限一覧

意図しない使用量を減らす

Paidでは1回あたりのCPU上限を設定できます。次は100msという説明用の値です。必要な処理に足りるか計測して決めます。これは月額の支出上限ではありません。呼び出し回数、保存量、AI利用などは別に制御します。

wrangler.jsoncのプロパティ断片:Paid向け
"limits": { "cpu_ms": 100 }

料金の確認では「何回呼ばれるか」「何を何回読み書きするか」「再試行が何回起こるか」を書き出します。ログの全件保存、D1の大量走査、R2の大量操作、AIの長い入出力も、アプリの総額に影響します。

先頭へ ↑
CHAPTER 17基礎

公開前に、入力・権限・秘密を確認する

Cloudflareが通信を保護していても、「他人のデータを編集してよいか」はアプリが判断します。小さいAPIでも、公開する前に境界を決めます。

認証:誰か

ログインセッションや署名付きトークンなどで本人を確認します。IDの文字列が届いただけでは本人確認になりません。

認可:何をしてよいか

ログイン済みでも、別の利用者のメモを読んだり編集したりできないよう、対象データの所有者を確認します。

実装で押さえる7点

  1. 入力:型、長さ、許可値、本文サイズを検証する。JSONを読めたことと、安全な入力であることは別。
  2. SQL:入力をSQL文字列へ連結せず、prepare(...).bind(...) で値を渡す。
  3. HTML:利用者入力をHTMLへそのまま埋め込まない。文字の表示には textContent などを使う。
  4. 秘密:Secretsに登録し、ブラウザやログへ返さない。漏れたキーは削除だけでなく失効・再発行する。
  5. 外部通信:利用者が渡す任意のURLをそのままfetchしない。許可する接続先を限定する。
  6. 回数:重い処理に利用者単位の回数制限を設け、上限に達したら停止する。
  7. データ:個人情報の必要量、保存期間、削除手段、バックアップ・復旧方法を決める。

CORSは、本人確認ではない

Originは「接続方式・ホスト・ポート」の組み合わせです。ブラウザが異なるOriginへリクエストするとき、応答を画面側のコードから読んでよいかを制御する仕組みがCORSです。

許可するOrigin、メソッド、ヘッダーを必要な範囲に絞り、必要に応じてOPTIONSの事前確認に応答します。Cookieなどの資格情報を使うときに Access-Control-Allow-Origin: * を安易に設定しないでください。CORSで許可しなくても、ブラウザ以外からAPIを呼ぶことはできます。認証・認可はサーバー側で必ず行います。

Cookieで認証するアプリでは、別サイトから意図しない更新操作を起こすCSRFへの対策も考えます。SameSite設定、Origin確認、CSRFトークンなどを、認証方式に合わせて選びます。

キャッシュと権限を組み合わせるとき

公開してよい静的画像と、利用者別の請求書では保存方針が違います。個人用APIは Cache-Control: no-store などで共有を防ぎ、明示的なキャッシュルールがそれを上書きしないかも確認します。キャッシュキーにユーザーIDを足せば、すべての認可問題が解決するわけではありません。

管理画面を作るなら:Cloudflare Accessなどのアクセス制御も検討できます。ただし、保護していない別のURL(workers.devやプレビューなど)から同じ処理へ到達できないか、公開先全体を確認します。

公式資料:Workersの実装上の推奨事項

公式資料:Custom DomainとAccess

先頭へ ↑
CHAPTER 18実習

実習:D1に保存する小さなメモAPI

入力を受け取り、検証し、データベースに保存して一覧を返す。ここまで学んだ基本を一つにつなげます。

ローカル実習専用です。この例にはログイン・所有者確認・回数制限を入れていません。メモを使って仕組みを学ぶためのコードです。このまま公開すると誰でも一覧を取得・追加できるため、個人情報を入れず、公開前に前章の認証・認可を追加してください。
POST /api/notes
titleを送る
Worker
形式・サイズを検証
D1
INSERTで保存
図6:その後、GET /api/notesで最新20件を取得します。

1. 新しいWorkerとD1を準備する

ターミナル:Worker only / JavaScript / デプロイNoを選ぶ
npm create cloudflare@latest -- notes-worker
cd notes-worker
npx wrangler d1 create notes-db

D1の作成コマンドはCloudflare上にデータベースを作ります。返された database_id を次の設定の指定箇所へ入れます。生成ツールが設定を追加した場合も、Binding名が DB か確認してください。

wrangler.jsonc:ファイル全体
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "notes-worker",
  "main": "src/index.js",
  "compatibility_date": "2026-09-17",
  "d1_databases": [{
    "binding": "DB",
    "database_name": "notes-db",
    "database_id": "作成コマンドが返したIDに置き換える"
  }],
  "observability": { "enabled": true }
}

2. 保存する表を作る

プロジェクトの直下に schema.sql を作ります。テーブルはデータを行と列で保存する単位です。id は行を識別する番号、title はメモ本文として使う短い文字列です。

schema.sql:ファイル全体
CREATE TABLE IF NOT EXISTS notes (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT NOT NULL
);
ターミナル:ローカルDBに表を作る
npx wrangler d1 execute notes-db --local --file=./schema.sql

--localは手元のDBが対象です。Cloudflare上のD1に同じ表を作る操作とは別です。本番ではスキーマ変更をマイグレーションとして履歴管理し、適用先を確認します。

3. Workerを書く

次はファイル全体です。長い部分の多くは入力検証で、保存処理自体は最後の prepare(...).bind(...).run() です。

src/index.js:ローカル実習用のファイル全体
function json(data, status = 200) {
  return Response.json(data, {
    status, headers: { "Cache-Control": "no-store" }
  });
}

// 本文を最大8KBまで読む。Content-Lengthだけには依存しない。
async function readSmallJson(request) {
  if (!request.body) throw new Error("empty");
  const reader = request.body.getReader();
  const chunks = [];
  let size = 0;
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    size += value.byteLength;
    if (size > 8192) {
      await reader.cancel();
      throw new Error("too_large");
    }
    chunks.push(value);
  }
  const bytes = new Uint8Array(size);
  let offset = 0;
  for (const chunk of chunks) {
    bytes.set(chunk, offset);
    offset += chunk.byteLength;
  }
  return JSON.parse(new TextDecoder().decode(bytes));
}

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    if (url.pathname !== "/api/notes") {
      return json({ error: "not_found" }, 404);
    }
    try {
      if (request.method === "GET") {
        const { results } = await env.DB.prepare(
          "SELECT id, title FROM notes ORDER BY id DESC LIMIT 20"
        ).all();
        return json({ notes: results });
      }
      if (request.method !== "POST") {
        return new Response("Method not allowed", {
          status: 405, headers: { Allow: "GET, POST" }
        });
      }
      const type = request.headers.get("Content-Type") || "";
      if (type.split(";")[0].trim().toLowerCase() !== "application/json") {
        return json({ error: "JSONで送ってください" }, 415);
      }
      let data;
      try {
        data = await readSmallJson(request);
      } catch (error) {
        return json({ error: "本文は8KB以内の正しいJSONにしてください" },
          error.message === "too_large" ? 413 : 400);
      }
      if (typeof data?.title !== "string") {
        return json({ error: "titleは文字列です" }, 400);
      }
      const title = data.title.trim();
      if (!title || title.length > 100) {
        return json({ error: "titleは1〜100文字にしてください" }, 400);
      }
      await env.DB.prepare("INSERT INTO notes (title) VALUES (?)")
        .bind(title).run();
      return json({ saved: true }, 201);
    } catch {
      console.error({ event: "notes_failed" });
      return json({ error: "保存サービスの処理に失敗しました" }, 500);
    }
  }
};

? に値を渡す bind(title) は、利用者入力をSQL命令として解釈させないために使います。title.length はJavaScriptの文字列長の数え方なので、絵文字などは見た目の1文字と一致しない場合があります。

4. 保存と読み出しを確認する

一つのターミナルで起動し、別のターミナルでリクエストを送ります。curl はHTTP通信を試すコマンドです。

ターミナルA:起動
npx wrangler dev
ターミナルB:POSTで作成 → GETで取得
curl -i http://localhost:8787/api/notes \
  -H 'Content-Type: application/json' \
  --data '{"title":"Workersを学ぶ"}'

curl -i http://localhost:8787/api/notes

最初は 201{"saved":true}、次は 200 とメモを含む一覧が期待結果です。さらに空タイトルは400、不正JSONは400、別パスは404、DELETEは405になることを試します。

ここまでできたら:「データを保存できた」だけでなく、「不正入力では保存されない」ことも確認できています。公開する次の段階では、認証済み利用者のIDを保存し、一覧取得もその利用者のデータだけに限定します。

公式資料:D1のはじめ方

公式資料:D1のPrepared statements

先頭へ ↑
CHAPTER 19応用

実践アーキテクチャ:目的に合わせて組み合わせる

最初から全部の製品を使う必要はありません。画面、処理、保存、非同期処理を分け、必要なものだけ加えます。以下は教材用の構成例です。

A. 小さな会員制Webアプリ

ブラウザ
画面を操作
Static Assets + Worker
画面配信 / 認証 / API
D1:会員・メモ
R2:添付ファイル
図7:R2にファイルを、D1に所有者・タイトル・ファイルキーを保存する構成例。

まずD1だけで文字データを扱い、添付機能が必要になったらR2を足します。R2のキーを知っていることと、読む権限があることは別です。ダウンロード時にWorkerで認可し、必要に応じて短期間だけ使えるURLを発行します。

B. 外部サービスからの通知を受け取る

Webhook送信元
Worker
署名・形式の検証
Queue
受け付けた仕事を保存
Consumer → D1
図8:Webhookは、イベント発生時に相手のURLへHTTP通知する仕組みです。

送信元の署名を検証し、キュー投入が完了してから受け付け成功を返します。ConsumerはイベントIDの重複を処理して、同じ通知で二重登録しないようにします。キューに入る前の受付失敗と、受け付け後の処理失敗を分けると復旧しやすくなります。

C. AIを使う問い合わせ支援

利用者の質問
Worker
認証 / 入力量 / 利用上限
AI Gateway
計測 / ポリシー
Workers AI または
外部AIプロバイダー
図9:Gatewayは任意の管理層です。WorkerからWorkers AIを直接利用する構成も可能です。

AIへの呼び出しには時間と費用がかかります。入力と出力の長さ、同時実行、利用者ごとの回数を決めます。AIの文章は事実確認済みとは限らないため、業務で使う場合は根拠の表示や人の確認を設計に含めます。保存する履歴とログには、個人情報の取り扱いも反映します。

D. 複数人で共有する部屋

複数の利用者
Worker
参加権限を確認
部屋ごとのDurable Object
同じ状態を調整
図10:同じ部屋名から同じオブジェクトを選ぶことで、その部屋の処理を集約する構成例。

チャットや共同操作では、部屋ごとに一貫した状態を扱える仕組みが役立ちます。一つの巨大なオブジェクトに全利用者を集めると負荷が集中するため、部屋や対象データごとの単位を考えます。メッセージ履歴などをどこまで永続化するかも明示します。

設計時に書き出す5つの質問

  1. 誰がどのURLへ、どの操作を送るか。
  2. 誰の権限で、どのデータを読む・書くか。
  3. その場で返す必要がある処理と、後でよい処理は何か。
  4. 同じ操作が2回来た場合や、途中で失敗した場合にどうするか。
  5. 1回あたり何を消費し、アクセス増加で何が増えるか。
先頭へ ↑
CHAPTER 20基礎

学習ロードマップと理解度チェック

一つずつ「自分で確認できる成果」を作ると、知識がつながります。日数を固定せず、達成条件を満たしてから次へ進みましょう。

段階やること進んでよい目安
1:Webの基礎DNS、HTTP、CDNの図を自分の言葉で説明する。DNSの問い合わせとWeb通信が違うと分かる。
2:最初のWorkerHello Worldを動かして文字を変える。編集するファイルと結果を見るURLが分かる。
3:APIパス、クエリ、JSON、ステータスを扱う。正常系・400・404・405を自分で再現できる。
4:保存D1にメモを保存する。ローカルとリモートのDBを区別できる。
5:公開公開してよいAPIをデプロイし、ログを見る。公開URLでの動作とエラーを確認できる。
6:運用認証・認可、利用上限、復旧方法を加える。他人のデータへのアクセスを拒否できる。
7:応用必要に応じてR2、Queues、AIなどを一つ追加する。追加する理由と、増える費用・失敗条件を説明できる。

自分の理解を確かめる

Q1. Workersを使うには、ドメインを買う必要がある?

最初は不要です。workers.devで始められます。独自ドメインは公開URLや運用条件に合わせて追加します。

Q2. Workerの先頭の変数に、会員のメモを保存してよい?

永続保存には使えません。実行領域が変わったり破棄されたりするため、D1などの保存サービスを使います。

Q3. KVで同時に売れる最後の1個の在庫を管理してよい?

単純なKVの読み書きでは適しません。結果整合性と同時更新の問題があるため、一貫した更新を扱えるデータベース設計やDurable Objectsなどを検討します。

Q4. CORSを設定すれば、APIは本人しか呼べなくなる?

なりません。CORSはブラウザからの読み取りを制御する仕組みです。サーバー側で認証・認可が必要です。

Q5. キューは必ず一度だけ届く?

重複配信される可能性があります。同じイベントIDを何度処理しても結果が壊れない設計にします。

Q6. AI Gatewayがあれば、AIモデル自体の利用料は不要?

別に考えます。Gatewayは呼び出しの管理層で、Workers AIや外部プロバイダーのモデル実行料金まで自動的に無料にするものではありません。

Q7. デプロイ成功だけで、アプリ完成と判断できる?

まだ確認が必要です。公開URLで正常・異常入力を試し、Bindings・権限・ログなどが正しく動くことを確認します。

次に読むテーマ

基本APIを作れたら、画面も配信するStatic Assets、ルートが増えたらルーターやフレームワーク、テストを増やすならWorkersのテスト環境へ進めます。長い複数段階の処理にはWorkflows、既存DBとの接続にはHyperdriveなどの選択肢があります。必要が生まれたときに公式資料を調べてください。

公式資料:Workers公式チュートリアル

公式資料:Workersのテスト

最初の到達点:「受け取る → 検証する → 処理・保存する → 結果を返す」を自分で実装し、失敗時の動作も確認できること。ここまでできれば、Workersを使った小さなアプリを段階的に育てられます。

先頭へ ↑
CHAPTER 21参照

用語集:分からない言葉を引く

用語この教材での意味
デプロイコードや設定を実行環境へ配置すること。
ランタイムプログラムを実行する環境。
エッジ利用者に近い側のネットワーク拠点を指す言葉。実行場所の保証とは別。
オリジン元のコンテンツや応答を提供するサーバー。文脈によりOriginはURLの接続方式・ホスト・ポートの組み合わせも指す。
エンドポイントAPIなどにアクセスする特定のURLや接続先。
ハンドラーイベントが来たときに呼び出される処理。
バインディング設定名とサービスや値を結び、コードから利用可能にする仕組み。
永続化実行中のメモリが消えた後も残る場所にデータを保存すること。
整合性複数の読み書きでデータがどう見えるかという性質。
結果整合性更新が直ちに全読取先へ反映されるとは限らず、時間とともに整合する性質。
冪等性(べきとうせい)同じ操作を繰り返しても、意図した最終結果が変わらない性質。
スキーマ / マイグレーションデータの表などの構造 / その構造の変更を履歴として管理・適用すること。
ストリーム全体を一度に保持せず、データを少しずつ受け渡す方式。
Webhookイベントが起きたとき、指定URLへHTTPで通知する仕組み。
Observabilityログや指標などから、実行中のシステムの状態を把握するための機能。
TTLキャッシュなどが有効な期間。
レート制限一定の時間内に許可する回数などの制限。
シークレットAPIキーなどの機密設定値。

公式資料の使い方

各章末のリンクはCloudflare・AWS・Google Cloudの公式ドキュメントです。料金・上限・設定方法は、使う直前にそのページを確認してください。ページの更新日、対象プラン、実験的機能かどうかも読みます。本文の構成図と練習問題は、この教材のために作成したものです。

教材確認日:2026年9月17日。製品の仕様やUIは変わります。学習用コードの検証範囲は巻末の「確認済みの範囲」に記載しています。本教材はCloudflare公式の発行物ではありません。

先頭へ ↑

著者: 藤川忠彦(ふじかわ ただひろ) — 企業向けAI導入アドバイザー、神奈川県茅ヶ崎市。

中央の赤い箱が上からの依頼を受けて三つの箱へ振り分ける図でCloudflare Workersを表した表紙画像
FUJIKAWA LAB SPECIMEN 48 / 48