CMSで更新したのにサイトに反映されない——キャッシュ4層の切り分け方
管理画面では新しいのに、クライアントの画面は古いまま。ヘッドレスCMS+Cloudflare構成で更新が止まるのは、ブラウザ・エッジ・オブジェクトキャッシュ・DBの4層のどれか。ヘッダーとServer-Timingで切り分ける手順と、層ごとの待ち時間の理屈を実測値つきでまとめます。

「昨日直した文章が、クライアントの画面ではまだ古いままなんです」。ヘッドレスCMSで作ったサイトを納品したあと、ディレクターからこう連絡をもらうことがある。管理画面では確かに新しい。自分のブラウザで開いても新しい。それでも、向こうでは古い。
この手の「反映されない」は、止まっている場所が4つのどれかに収まります。しかもレスポンスヘッダーを1回取るだけで、どの層かはかなり絞り込める。自分のサイト(Astro + EmDash + Cloudflare Workers)で実際に測った値を出しながら、切り分けの順番をまとめます。
更新が止まる場所は4つしかない
読者に近い側から並べます。
- ブラウザ。HTMLに保存の指示(
Cache-Control)が付いていれば、ブラウザは取りに行かず手元のものを見せる。 - エッジのHTMLキャッシュ。Cloudflare の Workers Cache を有効にしていると、サイトのプログラム(Worker)が動く前に保存済みのHTMLが返る。
- オブジェクトキャッシュ。ページを組み立てるためのデータベース読み取りの結果を、KVなどに置いておく層。EmDashではオプションで、記事の取得・サイト設定・メニュー・タクソノミーが対象です。
- データベース。ここが新しいなら、上の3つのどこかで止まっている。

潰す順番は下からです。まずAPIでデータが最新かを確かめ、上へ1層ずつ疑っていく。いきなり「Cloudflareのキャッシュを全部消す」に飛ぶと、直った理由が分からないまま次も同じ相談が来ます。
ヘッダーを1回取れば、どの層かが見える
手元のターミナルから1回叩くだけです。
curl -sS -o /dev/null -D - https://example.com/blog/some-post自分のサイトで取った実測(2026年8月)はこうでした。記事ページのHTMLには Cache-Control が付いておらず、CF-Cache-Status も返らない。HTMLはエッジにもブラウザにも保存されず、毎回 Worker が動いて組み立てているわけです。対して画像は Cache-Control: public, max-age=31536000, immutable。
EmDashはもう1つ手がかりを出してくれます。Server-Timing ヘッダーに、描画とミドルウェアの所要時間、DBのクエリ数、そして cache.hit と cache.miss の数が載っている。どこで時間を使ったかが、本番のレスポンスだけで分かります。

ここで一度つまずきました。cache.hit が毎回 0、cache.miss が2。KVが効いていないのかと疑いましたが、実装を読むと意味が違った。この2つが数えているのは 1リクエストの中で同じクエリを二度引いたか、というリクエストスコープの重複除去です。KVの効きはここには出ません。
KVが効いているかは、中身を見るのが早い。wrangler kv key list --namespace-id <id> --remote でキーの有効期限を控え、同じページを数回叩いてからもう一度見る。期限が動いていなければ、書き直さずに読めている。うちは em:settings:all の期限が3リクエストのあいだ動かないことを確認しました。名前だけで判断すると、直さなくていいものを直しにいく。
待ち時間には、層ごとの理屈がある
- オブジェクトキャッシュ:管理画面やREST API経由で編集すると、該当のキャッシュは自動で無効になります。ただし Cloudflare KV は各地のエッジへ伝わるまでに時間がかかり、EmDashのドキュメントは最大60秒程度と説明しています。加えて、isolate(Workerが動く実行単位)の中で値を使い回す窓(
revalidate・既定1秒)が乗ります。有効期間の既定は3600秒、KVでは最低60秒です。 - エッジのHTMLキャッシュ:
Cache-Controlを付けなければ保存されない、ではありません。Workers Cache は RFC 9111 のヒューリスティックに従い、ヘッダーの無い 200 応答を2時間保存します。有効にするなら全ルートに明示的な指定を置くのが前提。もう1つ、キャッシュは Worker より手前で動くのでCookieで分岐できません。ログイン中の編集者に匿名版のページが返ることがあり、EmDashにはこれを避けるtoolbar: "client"という設定があります(管理画面とAPIの応答はprivate, no-storeで、そもそも保存されません)。 - 予約公開:時刻が来ても、キャッシュ済みのページは「そのコレクションに次の変更が入るか、有効期間が切れるまで」古い一覧のままになり得ます。予約を使うサイトほど、有効期間は短めに。

キャッシュを足す目的は速度ですが、遅さの原因がキャッシュとは限りません。表示が遅いときは、どの区間で時間を使っているかを先に見ます(LCPが遅い原因は「内訳」でわかる)。
渡す前に決めておく3つ
- 反映までの時間を数字で伝える。「保存すればすぐ」ではなく「公開してから、行き渡るまで最大1分ほど」と手順書に書いておく。1分待てばいいと分かっていれば、問い合わせにはなりません。
- 確認はプレビューで。EmDashのプレビューとビジュアル編集はオブジェクトキャッシュを通らず、常に現在の内容を見せます(ヘッドレスCMSのプレビュー実装)。
- 画像は差し替えない。メディアは1年
immutableで配られるので、同じURLで中身を入れ替えても見た人の手元は古いまま。新規アップロードと貼り替えを手順書に1行入れる(CMSに上げた画像は自動で軽くならない)。
「反映されない」は、層さえ分かれば数分の話です。分からないまま全消しを繰り返すと、毎回1時間が溶けていきます。
ヘッドレスCMSでの構築や、既存サイトの「反映されない」の切り分けでお困りでしたら、お問い合わせからご相談ください。実装する側の目線で、構成と運用の手順までお手伝いします。
本記事は2026年9月時点の情報です。