Skip 4xx-response cache taag.

Created on 3 September 2025, 10 days ago

Describe your bug or feature request.

Drupal core uses the 4xx-response cache tag to deal with cache poisoning of 404 and other 4xx responses.

All those pages get that cache tag. Any entity with a canonical link template invalidates that cache tag on save.

This is done to prevent that someone could for example visit many node/X pages or other entity URLs, or guess path aliases and could therefore prevent

This isn't perfect but works. It's based on the assumption that entities aren't saved *that* often, so 404 pages are still valid for a while.

That is not true of course for commerce as every checkout saves the order on every step, so a single checkout invalidates that cache tag multiple times. On my site, the current count according to the redis report is "4xx-response: 41030". Caching those pages at all is pretty pointless then.

In theory, this would be very easy to trigger on commerce, because you don't usually use aliases, you can yourself create a order, increase the number by one and break the next checkout. At the same time, because being in checkout also implies having a session, so you don't get anonymous page cache and dynamic page cache isn't really affected by this, because it acts after routing. I did some manual testing and didn't manage to break it.

*If* that is true, then I think it's worth overriding \Drupal\Core\Entity\EntityBase::invalidateTagsOnSave() and remove that cache tag from affected entity types. I think that is only Order. All related entity types such as order item, payment and so on have no canonical link template

If a bug, provide steps to reproduce it from a clean install.

📌 Task
Status

Active

Version

3.0

Component

Order

Created by

🇨🇭Switzerland berdir Switzerland

Live updates comments and jobs are added and updated live.
  • Performance

    It affects performance. It is often combined with the Needs profiling tag.

Sign in to follow issues

Comments & Activities

  • Issue created by @berdir
  • 🇨🇭Switzerland berdir Switzerland
  • @berdir opened merge request.
  • 🇨🇭Switzerland berdir Switzerland

    Created a MR, only minimally tested.

  • 🇮🇱Israel jsacksick

    The change looks ok to me, and the tests are passing. Tempted to commit this, but wondering if we should wait a bit until this has been running on production for a while.

  • 🇮🇱Israel jsacksick

    What if... (really hypothetical scenario), a customer temporarily cannot access the order (for example, the order is "locked" and then unlocked), would the 403 page be cached and the save wouldn't invalidate that cached page?

    Also, I've always wondered whether we shouldn't force not caching the checkout pages.

  • 🇨🇭Switzerland berdir Switzerland

    Makes sense to wait a bit, I do plan to use this patch.

    > What if... (really hypothetical scenario), a customer temporarily cannot access the order (for example, the order is "locked" and then unlocked), would the 403 page be cached and the save wouldn't invalidate that cached page?

    For a regular Drupal site (excluding API/decoupled/... which is very different anyway), you always have a session. As soon as you have a session, pages are no longer cached externally or with internal page cache. The only thing that could possibly cache it is dynamic page cache.

    Testing locally, dynamic page cache gives me a
    x-drupal-dynamic-cache: UNCACHEABLE (poor cacheability)

    This is because the response object has user and session cache context. It is possible to configure this and cache stuff like this anyway but not recommended as you'd create a huge amount of cached pages that will likely never be used again.

    If you access an existing page, then that page includes cache tags. For example, if I manually request a checkout URL for an existing order with a known ID without the necessary session as anonymous user, then I'm getting a 403 and that also can be cached in page cache. But that response contains the commerce_order:ID cache tag, so if the access denied is because of the order state, any change to that order will invalidate this 403 page. So that should all be fine.

Production build 0.71.5 2024