「昨日直した文章が、クライアントの画面ではまだ古いままなんです」。ヘッドレスCMSで作ったサイトを納品したあと、ディレクターからこう連絡をもらうことがある。管理画面では確かに新しい。自分のブラウザで開いても新しい。それでも、向こうでは古い。

この手の「反映されない」は、止まっている場所が4つのどれかに収まります。しかもレスポンスヘッダーを1回取るだけで、どの層かはかなり絞り込める。自分のサイト(Astro + EmDash + Cloudflare Workers)で実際に測った値を出しながら、切り分けの順番をまとめます。

更新が止まる場所は4つしかない

読者に近い側から並べます。

  • ブラウザ。HTMLに保存の指示(Cache-Control)が付いていれば、ブラウザは取りに行かず手元のものを見せる。
  • エッジのHTMLキャッシュ。Cloudflare の Workers Cache を有効にしていると、サイトのプログラム(Worker)が動く前に保存済みのHTMLが返る。
  • オブジェクトキャッシュ。ページを組み立てるためのデータベース読み取りの結果を、KVなどに置いておく層。EmDashではオプションで、記事の取得・サイト設定・メニュー・タクソノミーが対象です。
  • データベース。ここが新しいなら、上の3つのどこかで止まっている。
更新が止まる場所は4つ。ブラウザ、エッジのHTMLキャッシュ、オブジェクトキャッシュ、データベース

潰す順番は下からです。まず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.hitcache.miss の数が載っている。どこで時間を使ったかが、本番のレスポンスだけで分かります。

ヘッダーで見分ける3つ。Cache-Control、CF-Cache-Status、Server-Timing

ここで一度つまずきました。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 で、そもそも保存されません)。
  • 予約公開:時刻が来ても、キャッシュ済みのページは「そのコレクションに次の変更が入るか、有効期間が切れるまで」古い一覧のままになり得ます。予約を使うサイトほど、有効期間は短めに。
オブジェクトキャッシュとエッジのHTMLキャッシュの比較。置くもの、消え方、待ち時間、注意点

キャッシュを足す目的は速度ですが、遅さの原因がキャッシュとは限りません。表示が遅いときは、どの区間で時間を使っているかを先に見ます(LCPが遅い原因は「内訳」でわかる)。

渡す前に決めておく3つ

  1. 反映までの時間を数字で伝える。「保存すればすぐ」ではなく「公開してから、行き渡るまで最大1分ほど」と手順書に書いておく。1分待てばいいと分かっていれば、問い合わせにはなりません。
  2. 確認はプレビューで。EmDashのプレビューとビジュアル編集はオブジェクトキャッシュを通らず、常に現在の内容を見せます(ヘッドレスCMSのプレビュー実装)。
  3. 画像は差し替えない。メディアは1年 immutable で配られるので、同じURLで中身を入れ替えても見た人の手元は古いまま。新規アップロードと貼り替えを手順書に1行入れる(CMSに上げた画像は自動で軽くならない)。

「反映されない」は、層さえ分かれば数分の話です。分からないまま全消しを繰り返すと、毎回1時間が溶けていきます。

ヘッドレスCMSでの構築や、既存サイトの「反映されない」の切り分けでお困りでしたら、お問い合わせからご相談ください。実装する側の目線で、構成と運用の手順までお手伝いします。

本記事は2026年9月時点の情報です。