従来のWebアプリケーションでは、ユーザーからのリクエストは遠く離れたデータセンターのオリジンサーバーまで到達し、処理結果が返ってくるまでに数百ミリ秒の遅延が発生していました。エッジコンピューティングは、ユーザーに地理的に近いロケーション(エッジ)でコードを実行することで、このレイテンシを劇的に削減する技術です。
Cloudflare Workersは、世界300以上の拠点で動作するサーバーレスプラットフォームです。V8エンジン上のIsolateで動作するため、コールドスタートがほぼゼロで、従来のLambdaなどのサーバーレスサービスとは一線を画す応答速度を実現します。筆者が実際にCloudflare Workersでプロダクションサービスを構築した経験から、実践的な入門ガイドをお届けします。
Cloudflare Workersの開発には、公式CLIツールのWranglerを使用します。
# プロジェクトの作成
npm create cloudflare@latest my-worker
cd my-worker
# ローカル開発サーバーの起動
npx wrangler dev
プロジェクトの設定はwrangler.tomlで管理します。
name = "my-api-worker"
main = "src/index.ts"
compatibility_date = "2024-10-01"
[vars]
ENVIRONMENT = "production"
[[kv_namespaces]]
binding = "CACHE_KV"
id = "xxxxxxxxxxxxxxxxxxxx"
[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "yyyyyyyyyyyyyyyy"
Workersの実装はWeb標準のFetch APIベースで行います。以下は、APIルーターを実装する例です。
export interface Env {
CACHE_KV: KVNamespace;
DB: D1Database;
ENVIRONMENT: string;
}
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext
): Promise<Response> {
const url = new URL(request.url);
switch (url.pathname) {
case "/api/articles":
return handleArticles(request, env);
case "/api/health":
return new Response(
JSON.stringify({ status: "ok", edge: request.cf?.colo }),
{ headers: { "Content-Type": "application/json" } }
);
default:
return new Response("Not Found", { status: 404 });
}
},
};
async function handleArticles(
request: Request,
env: Env
): Promise<Response> {
// KVキャッシュの確認
const cached = await env.CACHE_KV.get("articles:latest", "json");
if (cached) {
return Response.json(cached, {
headers: { "X-Cache": "HIT" },
});
}
// D1データベースから取得
const results = await env.DB.prepare(
"SELECT id, title, published_at FROM articles ORDER BY published_at DESC LIMIT 20"
).all();
// KVにキャッシュ(TTL: 5分)
await env.CACHE_KV.put(
"articles:latest",
JSON.stringify(results.results),
{ expirationTtl: 300 }
);
return Response.json(results.results, {
headers: { "X-Cache": "MISS" },
});
}
ここではrequest.cf?.coloでリクエストを処理しているエッジのロケーション(例えば東京ならNRT)を取得しています。これにより、実際にどのエッジで処理されているかをレスポンスヘッダーで確認できます。
Cloudflare Workersの強みは、エッジで利用可能な多様なストレージサービスが用意されている点です。
結果整合性のあるグローバル分散KVストアです。読み取りが高速で、キャッシュやセッション管理に適しています。書き込みの伝播に数秒かかるため、リアルタイム性が必要なデータには向きません。
エッジで動作するSQLiteベースのリレーショナルデータベースです。SQLが使えるため、複雑なクエリも記述可能です。以下のようにマイグレーションも管理できます。
# マイグレーションの作成
npx wrangler d1 migrations create my-app-db create_articles
# マイグレーションファイルの内容
-- migrations/0001_create_articles.sql
CREATE TABLE articles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT NOT NULL,
published_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_articles_published ON articles(published_at);
# マイグレーションの実行
npx wrangler d1 migrations apply my-app-db
S3互換のオブジェクトストレージで、エグレス費用がかからない点が最大の特徴です。画像やファイルの配信に最適で、大量のアセットをコスト効率よく配信できます。
Workersをオリジンサーバーの前段に配置し、レート制限、認証、キャッシュの機能をエッジで処理するパターンは非常に実用的です。オリジンへの負荷を大幅に削減できます。
async function rateLimit(
request: Request,
env: Env
): Promise<Response | null> {
const ip = request.headers.get("CF-Connecting-IP") || "unknown";
const key = `rate:${ip}`;
const current = parseInt(await env.CACHE_KV.get(key) || "0");
if (current >= 100) {
return new Response(
JSON.stringify({ error: "Rate limit exceeded" }),
{ status: 429, headers: { "Content-Type": "application/json" } }
);
}
await env.CACHE_KV.put(key, String(current + 1), {
expirationTtl: 60,
});
return null; // 制限内なら通過
}
Cloudflare Imagesと連携し、リクエストパラメータに応じて画像のリサイズやフォーマット変換をエッジで実行できます。CDNとの組み合わせにより、変換結果のキャッシュも効率的に行えます。
Workersには知っておくべき制約がいくつかあります。
本番デプロイは非常にシンプルです。
# 本番デプロイ
npx wrangler deploy
# プレビュー環境へのデプロイ
npx wrangler deploy --env staging
GitHub Actionsとの連携により、PRごとにプレビュー環境を自動デプロイする運用も容易に実現できます。デプロイは数秒で完了し、世界中のエッジに即座に反映されます。
Cloudflare Workersは、低レイテンシなAPI、エッジキャッシュ、APIゲートウェイなどの用途で非常に強力なプラットフォームです。D1、KV、R2といったストレージサービスの充実により、エッジだけで完結するアプリケーションの構築も現実的になりました。従来のサーバーレスとは異なる発想が必要な場面もありますが、適切なユースケースに適用すれば、コストとパフォーマンスの両面で大きなメリットを得られます。まずはシンプルなAPIから始めて、徐々にWorkersの世界を広げていくことをお勧めします。