Skip to content

Built-in FPC: save cacheable headers before setting no-cache headers (fixes #41643) - #41707

Open
bluefairydevelopment wants to merge 1 commit into
magento:2.4-developfrom
bluefairydevelopment:fix/41643-fpc-saves-no-store-headers
Open

bluefairydevelopment wants to merge 1 commit into
magento:2.4-developfrom
bluefairydevelopment:fix/41643-fpc-saves-no-store-headers

Conversation

@bluefairydevelopment

@bluefairydevelopment bluefairydevelopment commented Oct 26, 2026 •

Copy link
Copy Markdown

Description (*)

With the built-in full page cache, every cached page is saved with Cache-Control: no-store, so every cache HIT is sent to the browser (and any CDN in front of Magento) as non-cacheable, even though the page was cacheable and the FPC lookup succeeded.

Cause: in Magento\Framework\App\PageCache\Kernel::process(), $response->setNoCacheHeaders() runs before the cacheable-response branch, and getPreparedData() then snapshots $response->getHeaders() for fullPageCache->save(). Both act on the same response object, so the snapshot already contains the no-store Cache-Control. Kernel::load() / buildResponse() replay those saved headers on every HIT.

This change moves setNoCacheHeaders() to the end of the cacheable branch, after the page has been saved. The live response still gets its no-cache headers exactly as before; only the saved snapshot changes. Every other step (Set-Cookie and X-Magento-Tags clearing, cookie disabling, the save conditions) keeps its order.

Related Pull Requests

None.

Fixed Issues (if relevant)

  1. Fixes Built-in full page cache: Cache-Control stays no-store on a confirmed cache HIT (2.4.9) #41643

Manual testing scenarios (*)

  1. On 2.4-develop with the built-in full page cache enabled (system/full_page_cache/caching_application = 1) and production mode, flush the cache.
  2. Request the home page twice: curl -sI https://<store>/ | grep -iE '^(cache-control|x-magento-cache-debug)'
  3. Before this change: the second request shows X-Magento-Cache-Debug: HIT with Cache-Control: max-age=0, must-revalidate, no-cache, no-store.
  4. After this change: the second request shows X-Magento-Cache-Debug: HIT with Cache-Control: max-age=86400, public, s-maxage=86400.

We reproduced the problem on a clean 2.4.9 install with no third-party modules, on both Luma and a Hyvä theme. The same reordering, shipped as a DI preference, has been running since 2026-10-22/23 on two production stores and one staging store, where cache hits now serve public headers.

Unit test: KernelTest::testProcessSavesHeadersBeforeSettingNoCacheHeaders records the headers handed to fullPageCache->save(). Without this change it fails, because the saved Cache-Control is max-age=0, must-revalidate, no-cache, no-store. With it, the test passes. All Framework/App/Test/Unit/PageCache and Magento/PageCache/Test/Unit tests pass (147 tests), and phpcs (Magento2 standard) is clean on both changed files.

Questions or comments

setNoCacheHeaders() previously ran even when the response wasn't saved (e.g. a POST or a 500); it still does, because it stays inside the same outer Cache-Control: public … s-maxage condition.

Contribution checklist (*)

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All new or changed code is covered with unit/integration tests (if applicable)
  • README.md files for modified modules are updated and included in the pull request if any README.md predefined sections require an update
  • All automated tests passed successfully (all builds are green)

…ernel

Kernel::process() called setNoCacheHeaders() on the response before
getPreparedData() snapshotted its headers for the cache, so every page was
saved with Cache-Control: no-store and every cache hit replayed it. Set the
no-cache headers on the live response only after the page has been saved.

Fixes magento#41643
@ct-prd-projects-boards-automation ct-prd-projects-boards-automation Bot added the Priority: P2 A defect with this priority could have functionality issues which are not to expectations. label Oct 27, 2026
@github-project-automation github-project-automation Bot moved this to Pending Review in Pull Requests Dashboard Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority: P2 A defect with this priority could have functionality issues which are not to expectations. Progress: pending review

Projects

Status: Pending Review

Development

Successfully merging this pull request may close these issues.

Built-in full page cache: Cache-Control stays no-store on a confirmed cache HIT (2.4.9)

1 participant