← 記事一覧に戻る
テクノロジー

キャッシュ層を棚卸しして古いデータを防ぐ

キャッシュ層を棚卸しして古いデータを防ぐ

「更新したのに画面が変わらない」。この報告は、再現しないことが多く、開発側が最も扱いに困るバグの一つです。原因の多くは実装ミスではなく、どこに・どれだけの期間データを持つかを設計時に決めていなかったことにあります。この記事は設計工程の話として、キャッシュの層を先に棚卸しし、無効化の契機を決めてから実装する方法をまとめます。

なぜ「古いデータが見える」バグは起きるのか

キャッシュは性能のために後から足されがちです。「遅いからここにも入れよう」を繰り返すと、誰もすべての層を把握していない状態になります。すると更新した瞬間に、ある層は新しく、ある層は古いままという食い違いが生まれます。

  • 画面A(一覧)は新しいのに、画面B(詳細)は古い
  • 自分の端末では直ったが、同僚の端末では古いまま
  • リロードすると直るが、しばらくするとまた古くなる

どれも、キャッシュの層と寿命が頭の中にしかないことの症状です。

設計時に作る「キャッシュ層の棚卸し表」

実装に入る前に、データが通る経路上のキャッシュを全部書き出します。最低限、次の4層を見ます。

層

例

寿命の決まり方

無効化の契機

ブラウザ

HTTPキャッシュ、Service Worker

Cache-Control の max-age

URLにバージョンを付ける、再検証

CDN

Firebase Hosting、CloudFront など

s-maxage、CDN側の設定

パージ操作、ファイル名のハッシュ

アプリ(サーバー)

Rails.cache、メモ化

expires_in

更新時に該当キーを削除

クライアント状態

SWR、React Query、Redux

staleTime など

更新後に再取得(invalidate)

この表の「無効化の契機」欄が空白の行は、そのまま将来のバグ候補です。空欄を埋めるまで実装に進まない、というルールにするだけで効果があります。

層ごとに決めること

1. 何をキャッシュしてよいか

公開ページの静的な部分はキャッシュ向きです。一方、ログイン中の本人にだけ見えるデータや、更新直後に必ず見せたいデータ(保存した結果の画面など)は、CDNに載せないと決めておきます。ユーザー別のレスポンスには Cache-Control: private, no-store を明示します。

2. 寿命をいくつにするか

「何秒古くてもよいか」を機能ごとに決めます。ランキングなら5分でも許されますが、自分が今保存した内容が古く見えるのは許されません。許容できる古さを仕様として書いておくと、後から「バグか仕様か」で揉めません。

3. 誰が無効化するか

更新処理の中で、同じトランザクションの流れとして該当キャッシュを消す箇所を1か所に集めます。Rails の例です。

def update
  @article.update!(article_params)
  Rails.cache.delete(["article", @article.id])
  Rails.cache.delete(["article_list", @article.project_id])
end

更新箇所が複数に散らばると、1か所だけ消し忘れます。更新と無効化を同じメソッドにまとめるのが基本です。

「反映されない」報告を受けたときの切り分け順

報告が来たら、外側(ユーザーに近い層)から順に潰すと速く特定できます。

  1. ブラウザ: シークレットウィンドウ、または DevTools の Network で「Disable cache」にして再現するか。直るならブラウザ層
  2. ブラウザ(レスポンス): Network タブで該当リクエストを開き、Size 列が (disk cache) になっていないか。レスポンスヘッダの Cache-Control と Age も見る
  3. CDN: レスポンスの Age や X-Cache ヘッダを確認し、CDNが返していないか見る
  4. アプリ: サーバーのログで、DBまで届いているか、キャッシュから返しているかを確認する
  5. クライアント状態: 更新後に再取得が走っているか、ライブラリのキャッシュ設定を確認する

どの層で直ったかを記録しておくと、棚卸し表の抜けがそのまま見つかります。

失敗例: 層ごとに正しいのに全体で間違う

サーバーは更新時にキャッシュを消していて、CDNは60秒、ブラウザは5分の設定だった例です。各層は個別には妥当ですが、組み合わせると最長で約6分間、更新が見えません。層ごとの寿命は足し算になる、と覚えておくと設計時の見積もりがしやすくなります。

Bugoon での実践

「反映されない」報告は、報告者の環境の情報がないと切り分けが始まりません。Bugoon のウィジェットを埋め込むと、報告時のスクリーンショットに加え、ブラウザ・OS・画面サイズ、操作ステップ、Console のエラーやネットワークエラーが自動で添付されます。上の切り分け順の最初の数手を、開発者が聞き返さずに始められます。GitHub Issue に連携すれば棚卸し表の更新タスクとして起票でき、MCP サーバー経由で Claude Code や Cursor に渡して調査させることもできます。

チームのバグ報告を、もっとスムーズに。

Bugoon は無料で始められます。サイトにタグを 1 行追加するだけで、QA と開発の往復がなくなります。

無料で始める