リクエスト上限超過をルーティングの二重起動から切り分ける
今回やったこと
Workers と Pages Functions の日次リクエストを合算した値が上限を超えたとき、アクセスを一律に bot と決めつけず、同じ閲覧が複数の実行枠を消費していないかを調べた。2026年8月26日UTCの集計では、合計110,176件となり、Freeプランの日次100,000件を超過していた。原因の中心は、旧記事URLへのアクセスを処理する Worker が Pages へ subrequest を送る一方で、Functions 側も同じパスで起動していたことだった。
この記録は、リポジトリ内のPages Functionsミドルウェアとルート設定、およびAnalyticsの測定概要に基づく。集計値だけを見て料金プランを上げたり、利用者の User-Agent を遮断したりする前に、リクエストの経路を分解した事例である。
合計値の内訳を見る
Workers と Pages Functions は別々に数えられる。旧記事のパスを受けた Worker が Pages に問い合わせ、そのリクエストが Functions の対象にも含まれていれば、利用者から見た1回のアクセスが複数の実行として現れる。合計値だけでは、実際の閲覧が増えたのか、内部の転送が重複して計上されたのかを区別できない。
当時の時間別集計では、旧記事ルーターの42,258件と Pages Functions の64,948件の間に相関があり、相関係数は0.77だった。これは因果関係を単独で証明する値ではないが、両者の起動が同じ時間帯に動いているという手がかりになった。ミドルウェアのコメントには、旧記事処理が Pages へ subrequest を出す構造と、1アクセスで Worker と Function の両方が消費される問題が記録されている。
調査では、他の大きな数値もそのまま「無駄」とは扱わなかった。集計によると、Early Hints由来の20,205件はすべて504で Worker に到達しておらず、Safariの13,453件は5記事に集中する実読者と判断された。User-Agent を理由にSafariを遮断するのではなく、経路と応答を見て原因を分けた。botとして副作用なく落とせると切り分けられたのは1日4,241件だった。
起動範囲を狭めて確かめる
修正では、Functions の対象を指定する _routes.json の exclude に /archives/* を追加した。現在の設定は include: ["/*"] に対して、/archives/* を明示的に除外している。ミドルウェアにも、旧記事ルーターが Pages に問い合わせるため二重に枠を使っていたこと、除外を外すと日次枠を消費することがコメントとして残っている。
{
"include": ["/*"],
"exclude": [
"/archives/*",
"/_astro/*",
"/img/*"
]
}
この変更は「Functionsを全体停止する」のではなく、静的な旧記事解決に必要のない起動だけを避ける考え方である。ルート設定と実際のミドルウェアを照合し、除外後も必要な経路が残るかを確認する。設定ファイルだけを直して終わりにせず、Analyticsで変更前後のWorkersとFunctionsの数字を別々に見ると、二重起動の解消とアクセス減少を取り違えにくい。
修正後の見込みとして、上限超過日の約67,900件、通常日の約42,000件が記録されている。これは当時の集計にもとづく見込みであり、現在の負荷を保証する数値ではない。実際に採用する際は、同じ期間幅、同じルート定義、同じ集計条件で再計測する必要がある。
やってみてわかったこと
リクエスト上限に近づいたときは、ユーザー種別を先に疑うよりも、1回の操作がどの実行環境を何度通るかを図にする方が対処を絞りやすい。合算値の増加が二重起動なら、利用者を止めずにルーティングだけを直せる可能性がある。一方、相関だけで原因を断定することはできず、コード上の転送経路と変更後の計測を合わせる必要がある。
判断の順序は、サービス別のカウントを分離する、時間別に動きを比べる、コードで subrequest と起動条件を確認する、対象パスだけ除外して再計測する、となる。今回のように実読者と内部転送が混じる状況では、単一の User-Agent や総数を遮断条件にしないことが、利用者への副作用を避ける助けになる。
更新履歴
- 2026-09-29: 起稿。測定値は対象日を明記。