blog.dopana

Back

従来、グローバルにスケールする分散APIを構築するには、複数リージョンのコンテナ管理やデータベースのレプリケーション設定、複雑なリバースプロキシの調整が必要でした。

しかし、Cloudflareのエッジプラットフォームと Wrangler CLI を活用すれば、リレーショナルデータベース(D1)と超高速キャッシュ(KV)を統合したフルスタックREST APIをわずか数分で作成し、世界300箇所以上のデータセンターにゼロコールドスタートで即座にデプロイできます。

1. 全体像の理解(子どもでもわかる解説)#

システムを「一流のレストラン」に例えてみましょう:

  • Cloudflare Worker(ウェイター / シェフ): お客様のリクエストを受け取り、一番近い店舗(エッジ)でビジネスロジックを実行して素早く料理を提供します。
  • Cloudflare KV(作り置きのスピードカウンター / キャッシュ): よく注文される人気の料理を置いておく場所です。注文が入ると、厨房に行かずに一瞬で料理を渡せます(超高速な読み取り・1ms未満のレイテンシ)。
  • Cloudflare D1(メインの食材庫とレシピ帳 / データベース): 全てのデータが確実に保存されるSQLiteベースのサーバーレスデータベースです。正確なSQLクエリで安全にデータを管理します。
graph TD
    Client["📱 クライアント (Client Request)"] -->|HTTP GET/POST| Worker["⚡ Cloudflare Worker (Edge API)"]
    Worker -->|1. キャッシュ確認| KV["⚡ Cloudflare KV (超高速Readキャッシュ)"]
    KV -.->|Cache Hit - 即座に応答| Worker
    KV -.->|Cache Miss| D1
    Worker -->|2. データ検索/更新| D1["🗄️ Cloudflare D1 (Serverless SQLite)"]
    D1 -->|3. キャッシュ書き込み| KV
    Worker -->|HTTP JSON Response| Client

2. プロジェクトの準備と初期化#

Node.js または Bun がインストールされていること、およびCloudflareアカウントが準備されていることを確認してください。

ステップ1: Workerプロジェクトの作成#

npm create cloudflare@latest コマンドでTypeScriptテンプレートを作成します:

# TypeScriptテンプレートでWorkerを作成
npm create cloudflare@latest edge-api -- --type=hello-world-typescript --ts --git --deploy=false
cd edge-api
bash

最新のWrangler CLIをローカルにインストールします:

npm install -D wrangler
bash

CloudflareアカウントへCLIログインを実行します:

npx wrangler login
bash

3. Cloudflare D1(SQLデータベース)のセットアップ#

Cloudflare D1はSQLiteをベースにした分散サーバーレスリレーショナルデータベースです。

ステップ1: D1データベースの作成#

以下のコマンドで ecommerce-db という名前のD1データベースを作成します:

npx wrangler d1 create ecommerce-db
bash

コマンド完了後、設定用のバインディング情報が表示されます:

[[d1_databases]]
binding = "DB"
database_name = "ecommerce-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
text

ステップ2: スキーマ定義とマイグレーションの実行#

プロジェクトルートに schema.sql を作成します:

schema.sql
DROP TABLE IF EXISTS products;

CREATE TABLE products (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  price REAL NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO products (id, name, price) VALUES
  ('prod_1', 'ワイヤレスメカニカルキーボード', 129.99),
  ('prod_2', 'ウルトラワイドゲーミングモニター', 499.99),
  ('prod_3', '昇降式エルゴノミクスデスク', 349.50);
sql

ローカル開発環境でスキーマを実行します:

npx wrangler d1 execute ecommerce-db --local --file=./schema.sql
bash

本番(リモート)データベースでスキーマを実行します:

npx wrangler d1 execute ecommerce-db --remote --file=./schema.sql
bash

4. Cloudflare KV(Key-Valueキャッシュ)のセットアップ#

Cloudflare KVは高スループット・低遅延の読み取りに最適化されたグローバル分散ストレージです。

ステップ1: KVネームスペースの作成#

本番用とテスト/プレビュー用の2つのネームスペースを作成します:

# 本番用ネームスペース
npx wrangler kv namespace create CACHE_KV

# プレビュー用ネームスペース
npx wrangler kv namespace create CACHE_KV --preview
bash

出力されるID情報を控えておきます:

[[kv_namespaces]]
binding = "CACHE_KV"
id = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
preview_id = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
text

5. wrangler.toml の設定#

wrangler.toml にD1とKVのバインディングを追加します:

wrangler.toml
name = "edge-api"
main = "src/index.ts"
compatibility_date = "2026-08-01"

# D1 Databaseのバインド
[[d1_databases]]
binding = "DB"
database_name = "ecommerce-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# KV Cacheのバインド
[[kv_namespaces]]
binding = "CACHE_KV"
id = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
preview_id = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
toml

バインディング用のTypeScript型定義を自動生成します:

npx wrangler types
bash

6. Cache-AsideパターンによるAPIの実装#

src/index.ts にAPIロジックを実装します。Cache-Asideパターン を適用します:

  1. GET /api/products/:id 受信時、まずKVキャッシュを確認。
  2. キャッシュが存在する場合(HIT):即座にレスポンスを返却。
  3. キャッシュが存在しない場合(MISS):D1から取得し、TTLを設定してKVに書き込んだ上で返却。
  4. POST /api/products 受信時:D1にデータを新規保存し、KVキャッシュも更新。

[!TIP] キャッシュ保存処理を ctx.waitUntil(...) に委ねることで、非同期書き込み完了を待たずにクライアントへ最速でレスポンスを返せます。

7. ローカル検証と本番デプロイ#

ローカル開発サーバーの起動#

ローカル環境でD1とKVをエミュレートして実行します:

npx wrangler dev
bash

curl コマンドで動作を確認します:

# 1回目のリクエスト(MISS - D1から読み込み)
curl http://localhost:8787/api/products/prod_1

# 2回目のリクエスト(HIT - KVキャッシュから即座に返却)
curl http://localhost:8787/api/products/prod_1
bash

本番環境へのデプロイ#

世界中のCloudflareエッジネットワークへ1コマンドでデプロイします:

npx wrangler deploy
bash

デプロイ完了後、https://edge-api.<subdomain>.workers.dev のようなURLが発行され、世界300以上の都市から即座に利用可能になります!

8. Rust と Axum を使用する場合の違い#

TypeScriptの代わりにRustの厳格な型安全性と高パフォーマンスを求める場合、Cloudflare WorkersはRustコードをWebAssembly(wasm32-unknown-unknown)にコンパイルし、worker-rs を介して Axum フレームワークをエッジ上で動作させることができます。

アーキテクチャ比較: TypeScript vs Rust (Axum)#

graph LR
    subgraph TS["TypeScript Worker"]
        direction TB
        TS_Code["src/index.ts"] --> V8["V8 Isolate エンジン<br/>(ネイティブJSバインディング)"]
        V8 --> DB_TS["env.DB / env.CACHE_KV"]
    end

    subgraph RS["Rust + Axum Worker"]
        direction TB
        RS_Code["src/lib.rs (Axum Router)"] --> WASM["WASM モジュール<br/>(wasm32-unknown-unknown)"]
        WASM --> WRS["worker-rs FFI ブリッジ"]
        WRS --> DB_RS["env.d1('DB') / env.kv('CACHE_KV')"]
    end
比較項目TypeScriptRust (Axum + worker-rs)
コンパイル対象JavaScript (V8 Isolate上で直接実行)WebAssembly (.wasm) worker-build経由
ルーティング構成標準の fetch(request, env, ctx)axum::Router と Extractor (State, Path, Json)
バインディング取得ネイティブオブジェクト: env.DB, env.CACHE_KVworker::Env FFI経由: env.d1("DB")?, env.kv("CACHE_KV")?
パフォーマンスと安全性迅速なプロトタイピング、ビルド時型チェックメモリ安全性、ゼロコスト抽象化、コンパイル済みWASM
wrangler.toml 設定main = "src/index.ts"main = "build/worker/shim.mjs" + [build] command = "worker-build --release"

Rust Axum による D1 & KV 実装例#

Rustでは、Workerのエントリポイント内で axum::Router を生成し、Axumの State を通じて worker::Env を共有します:

9. Wrangler CLI 主要コマンド早見表#

コマンド説明
wrangler loginCloudflareアカウントとの認証
wrangler devD1 & KV対応ローカルエミュレータ起動
wrangler d1 create <name>新規D1データベースの作成
wrangler d1 execute <name> --file=./schema.sqlSQLファイルの実行(--local または --remote
wrangler kv namespace create <name>新規KVネームスペースの作成
wrangler typesTypeScript型定義の自動生成
wrangler deployWorkerをグローバル本番環境へデプロイ
wrangler tail本番環境のリアルタイムログをターミナルで確認

参考文献#