最近仕事で Cloudflare Workers を使う機会が増えてきた。CDN のエッジで処理を書けるのは便利だけど、キャッシュ戦略をちゃんと考えないとパフォーマンスが全然違う。
今回は Workers を使ったエッジキャッシュ最適化の実践的なテクニックをまとめる。
Workers には caches.default という組み込みのキャッシュストレージがある。これを使うとオリジンにリクエストを飛ばさずにエッジでレスポンスを返せる。
// Cloudflare Workers でのキャッシュ例
async function handleRequest(request) {
const cacheKey = new Request(request.url, request)
const cache = caches.default
// キャッシュ確認
let response = await cache.match(cacheKey)
if (response) {
return response
}
// オリジンにフェッチ
response = await fetch(request)
// キャッシュに保存(TTL はヘッダーで制御)
const headers = new Headers(response.headers)
headers.set('Cache-Control', 'public, max-age=3600, s-maxage=86400')
const cachedResponse = new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers
})
// 非同期でキャッシュ(レスポンスはすぐ返す)
ctx.waitUntil(cache.put(cacheKey, cachedResponse.clone()))
return cachedResponse
}
Cloudflare の Cache-Tag 機能を使うと、特定のタグが付いたキャッシュだけを選択的にパージできる。API のバージョン更新時などに便利。
// Cache-Tag を付与する
response.headers.set('Cache-Tag', 'api-v2,user-profile')
// ← Purge by Tag で "api-v2" だけ削除できる
最近のベストプラクティスとして、stale-while-revalidate を使うとキャッシュが expired してもすぐにはオリジンに飛ばさず、古いキャッシュを返しながらバックグラウンドで新しいキャッシュを取得する。
Cache-Control: public, max-age=300, stale-while-revalidate=86400
この設定だと、5分経ってもユーザーには即座にレスポンスが返り、サーバーへの負荷も最小限になる。
この最適化を導入した結果、オリジンサーバーの負荷が約70%削減され、ユーザー体感のレスポンスタイムも平均 200ms → 45ms に改善された。
特に日本→アメリカのオリジンに対しては、Cloudflare の東京エッジにキャッシュされる恩恵が大きい。
次回は Workers KV と D1 を使ったデータベースレス設計について書く予定。