ネットワークの「溜まり」を制する者はレスポンスを制す:Cache-Control徹底攻略
ネットワークエンジニアとして数多のトラフィックを眺めてきたが、API設計の甘さが招く「キャッシュの不整合」ほど厄介なものはない。APIサーバーにリクエストを投げれば投げるほどDB負荷が増大し、ユーザー体験がガタ落ちする……そんな悲劇を未然に防ぐのが、HTTPヘッダーの華、Cache-Controlだ。
今回は、RFC 9111(HTTP Caching)の深淵を覗きつつ、現場で本当に使えるキャッシュ戦略を叩き込む。
—
1. キャッシュの「立ち位置」を理解する
まず大前提として、キャッシュは「ブラウザ(クライアント)」と「中間サーバー(CDNやプロキシ)」という二つの領分があることを理解しなければならない。
max-age: クライアント(ブラウザ)にどれだけキャッシュさせるか。s-maxage: CDNやプロキシサーバーにどれだけキャッシュさせるか。
ここを混同して「とりあえず max-age=3600」と指定すると、CDNが効かずオリジンが死ぬか、逆にブラウザが古いデータを握りしめて離さない地獄絵図が待っている。
よく使うディレクティブの急所
no-store: 最強の拒絶。 どこにも保存させない。機密情報(個人情報など)を扱うAPIでは必須だ。no-cache: 「キャッシュするな」ではない。 「使う前に必ずサーバーに再検証(ETag比較など)をかけろ」という命令だ。must-revalidate: キャッシュが期限切れになったら、必ずサーバーに確認を取れという強制力。これがないと、不安定なネットワーク下で古いデータが返るリスクがある。
—
2. 現場で「使える」設定例
APIアーキテクトとして、以下の3つのパターンを使い分けるのが「美学」だ。
パターンA:頻繁に更新されるリソース(非公開API)
更新頻度が高いなら、キャッシュさせつつも再検証を求める設定にする。
# 毎回ETagでサーバーに「変わってない?」と聞く
Cache-Control: no-cache
パターンB:静的なAPIレスポンス(CDN活用)
一度取得したら一定時間はサーバーを叩かせない。CDNの恩恵を最大化する設定だ。
# 5分間はCDNにキャッシュし、ユーザーのブラウザにも1分間持たせる
Cache-Control: public, s-maxage=300, max-age=60
パターンC:個人情報・秘匿データ
キャッシュ厳禁。ブラウザの履歴にも残したくない場合はこれで決まりだ。
# キャッシュを一切許さない
Cache-Control: no-store, no-cache, must-revalidate
—
3. 実践:curlでキャッシュの挙動を追跡する
構築したAPIが想定通りに動いているか。ブラウザのデベロッパーツールも良いが、ネットワークエンジニアなら curl でヘッダーを叩き込むのが一番早い。
# ヘッダー情報を取得し、キャッシュの挙動を確認する
curl -I -v https://api.example.com/v1/resource/123
レスポンスの X-Cache ヘッダー(CDNベンダーによる)や Age ヘッダーに注目してほしい。Age が増えていれば、それはキャッシュサーバーが守ってくれている証拠だ。
—
4. Python (FastAPI) での実装例
バックエンド側でこれらをどう制御するか。FastAPIの例を見てみよう。
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int, response: Response):
# 300秒間キャッシュさせる設定を付与
response.headers["Cache-Control"] = "public, s-maxage=300, max-age=60"
return {"item_id": item_id, "data": "ここに重いレスポンスが入る"}
このように、レスポンスオブジェクトに明示的に Cache-Control を付与するのが、モダンなAPI設計の基本だ。
—
5. シニアエンジニアからの教訓:トラブルを避けるために
最後に、現場で泣きを見ないためのTipsを一つ。
「キャッシュの削除(パージ)は神ではない」
CDNのキャッシュをパージするAPIを叩く運用に頼りすぎると、ネットワークの疎通遅延やAPI制限で痛い目を見る。基本は「キャッシュ時間を短くする」か「URI自体にバージョンを含める(/v1/items/123)」ことで、キャッシュの無効化を制御する設計を目指してほしい。
キャッシュは、正しく設定すれば最強の味方だが、理解を怠れば最もデバッグが困難な敵となる。まずは curl -I を叩く習慣をつけ、パケットがどこで止まり、どこで再利用されているのかを可視化することから始めよう。
ネットワークの深淵を愛する諸君、健闘を祈る。
コメント