先週末、ランディングページからのフォーム送信を受け取るための公開エンドポイントが必要でした。 凝ったものではなく — JSON POSTを受け取り、いくつかのフィールドを検証し、適切な応答を返すだけ。 全体で週に50リクエストくらいを処理する程度でした。月20ドルのサーバーのためにクレジットカードを登録したり、 新しいインフラツールを学んだり、3行変更するたびにCIパイプラインを待ったりはしたくありませんでした。 始めて10分後には、APIは300以上の都市でライブで動作しており、コストはゼロドルでした。これがその手順です。

Cloudflare Workers には実際に太っ腹な無料プランがあります:1日10万リクエスト、サインアップにクレジットカード不要、 そしてコードは1つのリージョンではなくエッジで実行されます。多くのサイドプロジェクトが必要とする小さなAPI — webhookレシーバー、フォームハンドラー、リンク短縮、JSONプロキシ — については、デプロイして忘れることができます。 このガイドでは、「Cloudflareアカウントなし」から「curlに応答するライブURL」まで約10分で進みます。 実際のエンドポイントを構築します:POSTを受け取り、ペイロードをチェックし、きれいな応答をエコーバックする JSONバリデーターです。

無料で得られるもの(と得られないもの)

Cloudflare Workersの 無料プラン は、1日10万リクエストとリクエストあたり10ミリ秒のCPU時間を提供します。これは厳しく聞こえますが、 ほとんどのJSONエンドポイント — ボディをパースし、ちょっとした処理をして、応答を返す — は1ms未満で楽に終わると 気づくと話が変わります。10msの上限はCPU時間であり、ウォールクロック時間ではないので、800msかかるアップストリーム fetchも、コードはほとんどI/O待ちなので、約1msのCPUとしてカウントされます。

無料プランで得られないもの:高スループットの永続ストレージ (Workers KV には独自の無料枠があります — ほとんどの場合は寛大ですが、リクエスト数とは別物です)、大きなレスポンスペイロード、 または1分に1回より頻繁なスケジュールクロントリガー。データベースが不要な典型的な「JSONを受け取り、何かして、JSONを返す」 サービスでは、壁にぶつかることはないでしょう。

サインアップにクレジットカード不要。アカウントを作成するとき、Cloudflareは メールアドレスとパスワードを尋ねるだけです — それだけです。ダッシュボードは後ほど有料製品のために課金情報の追加を 促してきますが、無料のWorkers枠は何も必要とせず、想定外の請求もありません。

Node.jsとWranglerをインストールする

WranglerはCloudflareのWorkers向けCLIです。npm経由でインストールします — Node.js 18以降が必要です。 すでにNodeがあれば、ワンライナーです:

bash
npm install -g wrangler

# Verify
wrangler --version
# Should print 3.x or higher

次にログインします。これはOAuthのためにブラウザを開き、Cloudflareアカウントがなければ作成し、 認証情報をローカルに保存します:

bash
wrangler login

# Opens https://dash.cloudflare.com/oauth/authorize ...
# After you approve: "Successfully logged in."

プロジェクトをスキャフォールドする

1コマンドで、まともなデフォルトを備えたプロジェクトの骨組みが手に入ります — サンプルの fetchハンドラ、wrangler.toml設定、そしてローカル開発サーバーがすでに配線されています:

bash
npm create cloudflare@latest free-json-api

# When prompted, pick:
#   "Hello World" Worker
#   JavaScript (or TypeScript — your call)
#   No deploy yet (we'll do that ourselves)

cd free-json-api

ジェネレーターは必要なものすべてを1つのフォルダに入れてくれます。src/index.jsを開いてください — これがWorkerが実行するファイルです。デフォルトのHello Worldより役に立つもので中身を置き換えます。

JSON APIを書く

JSON POSTを受け取り、2つの必須フィールドを検証し、きれいな応答を返す完全なWorkerがこちらです。 一般的な失敗モード — 間違ったメソッド、不正なJSON、欠けているフィールド — を、汎用的な500にクラッシュする代わりに 処理します:

js
export default {
  async fetch(request) {
    if (request.method !== 'POST') {
      return Response.json(
        { error: 'POST only' },
        { status: 405 },
      );
    }

    let body;
    try {
      body = await request.json();
    } catch {
      return Response.json(
        { error: 'Body must be valid JSON' },
        { status: 400 },
      );
    }

    const { email, message } = body;
    if (typeof email !== 'string' || typeof message !== 'string') {
      return Response.json(
        { error: 'email and message are required (strings)' },
        { status: 422 },
      );
    }

    return Response.json({
      ok: true,
      receivedAt: new Date().toISOString(),
      echo: { email, message },
    });
  },
};

指摘しておきたい点が2つあります。 Response.json() はオブジェクトをシリアライズし、Content-Type: application/jsonを自動で設定してくれるので、 ヘッダーを覚えておく必要はありません。そしてrequest.json()をtry/catchで囲むことは、 Workersを構築する際に最も重要な習慣です — これがないと、不正なペイロードはコードからの有用な400ではなく、 Cloudflareランタイムからの不透明な500を返します。

ローカルでテストする

WranglerにはCloudflareが本番で使っているのと同じV8 isolateを実行するローカル開発サーバーが付属しています。 これで起動します:

bash
npm run dev

# ⛅️ wrangler 3.x
# [wrangler:inf] Ready on http://localhost:8787

別のターミナルで、curlで叩きます。まずハッピーパスを試し、それから意図的に壊した ペイロードを試してください — スタックトレースではなく、きれいなJSONエラーが見えるはずです:

bash
# Happy path
curl -X POST http://localhost:8787 \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","message":"hello"}'

# {"ok":true,"receivedAt":"2025-10-15T...","echo":{...}}

# Broken JSON (note the missing closing brace)
curl -X POST http://localhost:8787 \
  -H "Content-Type: application/json" \
  -d '{"email": "ava"'

# {"error":"Body must be valid JSON"}

# Missing required field
curl -X POST http://localhost:8787 \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}'

# {"error":"email and message are required (strings)"}
ヒント:応答がターミナルでおかしく見える場合は、JSON Formatterに 貼り付けて整形し検査してください。馴染みのないAPIを扱うとき、私はこれを1日に20回はやります。

世界中にデプロイする — 1コマンドで

ローカルで動いたら、グローバルにプッシュしましょう:

bash
npx wrangler deploy

# Total Upload: 1.18 KiB / gzip: 0.55 KiB
# Uploaded free-json-api (1.34 sec)
# Published free-json-api (4.21 sec)
#   https://free-json-api.<your-subdomain>.workers.dev
# Current Deployment ID: ...

そのURLは、すべてのCloudflareデータセンターでライブになっています。ベルリンからのリクエストはフランクフルトに、 東京からは東京に、サンパウロからはサンパウロにヒットします — 同じコード、追加の設定なし。バンドルは1.2 KiBでした。 ローカルで使ったのと同じcurlコマンドでライブURLをテストしてください — localhost:8787を Wranglerが表示したworkers.devのホスト名に置き換えるだけです。

無料枠を超えるとき

長い間、超えることはありません。1日10万リクエストは、24時間平均で1秒あたり約1.15リクエスト — ほとんどのサイドプロジェクト、社内ツール、初期段階の製品が処理する量より十分多いです。通常、無料枠から押し出すのは リクエスト数ではなくストレージです:KV、R2、D1への書き込みが多くなり始めると、それらには独自のクォータがあります。 有料プラン は月5ドルから始まり、1000万リクエスト、リクエストあたりのCPU増加、そしてスパイクのためのクレジットカードによる 安全網を提供します。ほとんどのプロジェクトは必要としません。

次に

あなたが出荷したのは、最低限有用なWorkerです。本番のリアルなエンドポイントには、もう少しの習慣が必要です — ブラウザ呼び出し元のためのCORS、APIキーのためのシークレット管理、遅いアップストリームのためのエッジキャッシング、 そしてアップストリームサービスをプロキシする戦略。それらを Cloudflare WorkersとJSON — 実践ガイド でカバーしました。この記事の終わりから引き継いでいます。

JSONを扱うWorkerを構築する際に開いておくツールをいくつか:応答を整形するための JSON Formatter、なぜペイロードが拒否されたのか正確に把握するための JSON Validator、そして書く前にフィールド抽出ロジックを計画するための JSON Path。JSON形式自体は RFC 8259 で仕様化されています — 実際のユーザーからの奇妙な入力を扱い始めたら、ざっと目を通す価値があります。

より深いWorkerパターン — KVストレージ、Durable Objects、スケジュールトリガー、AI推論バインディング — については、 Cloudflareの Workersサンプルギャラリー が私が見つけた最高のリソースです。次のステップのためのコピペ可能なレシピのリストです。

まとめ

Cloudflare Workersは、本物のサイドプロジェクトに実際に使える、まれな無料枠です。始めるのに クレジットカード不要、1日10万リクエスト、そして1コマンドに収まるデプロイストーリー。この記事のパターン — JSONを受け取り、検証し、JSONを返す — は、ほとんどのAPIがやることのうち驚くほど多くをカバーします。 インフラが面倒だからと小さなAPIの出荷を先延ばしにしていたなら、これが3年前に取りたかった道です。