
CloudFront の Origin Shield で S3 へのクロスリージョン参照性能が改善するか試してみた
はじめに
DevelopersIO のフロントは Next.js アプリで、Lambda Web Functions(LWF)のグローバルエンドポイントを使い、複数リージョンで動く構成になりました。
著者ページのグラフを描画するため、バージニアに保存した集計済みの JSON を CloudFront 経由で取得しています。

LWF への切り替え後、グラフの欠落報告が寄せられ、アプリログにも JSON の取得が 500ms でタイムアウトした記録が出ていました。
そこで、Origin Shield で JSON 取得の遅延を解消できるかを検証環境で実測し、LWF 環境に導入した結果を紹介します。
エッジにキャッシュがない状態で取得時間を測る
Origin Shield なしの CloudFront ディストリビューションを作りました。
S3 バケットは us-east-1 に置き、本番の著者別集計 JSON 1,183件から選んだ200件(gzip 圧縮、128〜714バイト)をコピーしました。ディストリビューションはこのバケットを OAC(Origin Access Control)経由で参照します。キャッシュポリシーは、クエリ文字列 k をキャッシュキーに含める独自のものを使いました。k の値を変えると別のオブジェクトとしてキャッシュされるので、キャッシュを無効化しなくても、毎回キャッシュがない状態から測れます。
計測用のキャッシュポリシー(cache-policy.json)
{
"Name": "oss-verify-cachingoptimized-qs-k",
"Comment": "Managed-CachingOptimized と同じ TTL・圧縮。クエリ文字列 k だけをキャッシュキーに含める(計測用)",
"MinTTL": 1,
"DefaultTTL": 86400,
"MaxTTL": 31536000,
"ParametersInCacheKeyAndForwardedToOrigin": {
"EnableAcceptEncodingGzip": true,
"EnableAcceptEncodingBrotli": true,
"HeadersConfig": {"HeaderBehavior": "none"},
"CookiesConfig": {"CookieBehavior": "none"},
"QueryStringsConfig": {"QueryStringBehavior": "whitelist", "QueryStrings": {"Quantity": 1, "Items": ["k"]}}
}
}
計測には AWS Lambda Event Function(従来の Lambda。Node.js 22、メモリ 512MB)を4リージョンに1つずつ置きました。各 Event Function は200ファイルを1件ずつ順に取得し、取得ごとの時間を記録します。1ラウンドの手順は次のとおりです。
- クエリ文字列 k を新しい値にする。
- us-east-1 の Event Function が200ファイルを取得する。エッジにも Origin Shield にもキャッシュがない状態なので、S3 まで取りに行く。
- 残り3リージョンの Event Function が並行して、同じ k で同じ200ファイルを取得する。
手順3のレスポンスの x-cache ヘッダーは、Origin Shield 有効化前は3リージョンとも Miss from cloudfront でした。有効化後はすべて Hit from cloudfront でした。エッジにはキャッシュがないので、このヒットは Origin Shield のものです。つまり、有効化前の値は S3 まで取りに行ったとき、有効化後の値は Origin Shield のキャッシュにヒットしたときの取得時間です。
計測用 Event Function のコード(index.mjs)
// 計測用 Event Function(従来の Lambda)。
// event: { base, prefix, k, files: [..] }
// https://<ディストリビューション>/<prefix><file>?k=<k> を順に取得して所要時間を記録する
const now = () => performance.now();
export const handler = async (event) => {
const rows = [];
const url = (f, k) => `${event.base}/${event.prefix}${f}?k=${k}`;
// 接続の確立(別のキーで取得。計測に含めない)
try { const w = await fetch(url(event.files[0], "warm-" + event.k)); await w.arrayBuffer(); } catch (e) {}
for (const f of event.files) {
const t0 = now();
let status = 0, ttfb = 0, xc = "", pop = "", bytes = 0;
try {
const r = await fetch(url(f, event.k), { signal: AbortSignal.timeout(10000) });
ttfb = now() - t0;
status = r.status; xc = r.headers.get("x-cache") ?? ""; pop = r.headers.get("x-amz-cf-pop") ?? "";
bytes = (await r.arrayBuffer()).byteLength;
} catch (e) { status = -1; xc = String(e.name); }
const t = now() - t0;
rows.push([f, status, +ttfb.toFixed(1), +t.toFixed(1), xc, pop, bytes]);
}
return { region: process.env.AWS_REGION, k: event.k, columns: ["file", "status", "ttfb_ms", "total_ms", "x_cache", "pop", "bytes"], rows };
};
計測結果
Origin Shield なし
8ラウンド(各リージョン1,600件)の取得時間(ms)です。
| 呼び出し元 | p50 | p90 | p95 | p99 |
|---|---|---|---|---|
| ap-northeast-1 | 493.8 | 512.5 | 523.3 | 583.8 |
| eu-central-1 | 311.7 | 329.4 | 339.8 | 394.5 |
| us-west-2 | 250.9 | 271.0 | 281.5 | 327.7 |
| us-east-1 | 45.2 | 63.8 | 78.3 | 129.4 |
有効化前の ap-northeast-1 は p50 で 493.8ms でした。
Event Function(メモリ 512MB)と比べて LWF は高い CPU 性能が期待できますが、本番で設定しているタイムアウト 500ms に対して余裕がない状態であることが確認できました。
Origin Shield あり
S3 バケットと同じ us-east-1 を指定して、Origin Shield を有効化しました。
有効化後の2ラウンド(各リージョン400件)の取得時間(ms)です。
| 呼び出し元 | p50 | p90 | p95 | p99 | p50 の短縮 | p95 の短縮 |
|---|---|---|---|---|---|---|
| ap-northeast-1 | 159.5 | 164.2 | 165.0 | 177.0 | 334.3ms(68%) | 358.3ms(68%) |
| eu-central-1 | 102.0 | 104.9 | 106.1 | 125.9 | 209.7ms(67%) | 233.7ms(69%) |
| us-west-2 | 84.5 | 91.0 | 94.9 | 105.3 | 166.4ms(66%) | 186.6ms(66%) |
| us-east-1 | 50.0 | 67.5 | 77.8 | 120.5 | − | − |
Origin Shield を有効にすると、us-east-1 以外の3リージョンで取得時間の短縮が確認できました。
追加費用の見積もり
Origin Shield へのリクエストの料金は、us-east-1 の場合1万件あたり $0.0075 です。
JSON のダウンロードは、実測で多くても1日1万回です。うち3/4が us-east-1 以外のリージョンから Origin Shield を経由すると置いて計算しました。
7,500件/日 × 30日 = 22.5万件 → 22.5 × $0.0075 ≒ $0.17/月
エッジのキャッシュにヒットしたリクエストは Origin Shield に届かず課金されないので、実際はさらに少なくなる見込みです。
まとめ
Origin Shield の有効化により、S3 から小容量のファイルを取得する時間が p50 で 170〜330ms 短くなりました。本番環境にも導入し、問題になっていたタイムアウト(500ms)も概ね解消できました。
Lambda Web Functions で複数リージョン展開し、データソースの S3 を CloudFront 経由で参照している構成で、S3 参照の遅延が問題になる場合は、まず Origin Shield を暫定策としてお試しください。
根本対策としては、S3 をリージョン間でレプリケーションし、最寄りのバケットにアクセスできる Amazon S3 マルチリージョンアクセスポイント(グローバルエンドポイント)が考えられます。こちらも追って評価し、紹介する予定です。









