Skip to content

Smart invalidation deep-dive

Smart invalidation is the default mode. Instead of purging “everything related to product X” when a product changes, it inspects which fields actually changed and computes the minimum set of cache tags that must die.

This page explains the field-to-tag mapping so you can predict what a given save will invalidate — and decide whether Smart is right for your store.

Stock Shopware invalidation operates at the entity level: any change to product X invalidates everything tagged with product-X. That tag is typically attached to:

  • The product detail page
  • Every category page the product appears on
  • Every listing query that returned the product
  • The async buybox component
  • The home page if the product is featured

So a one-character fix in the description re-renders dozens of pages — many of which don’t even display the description.

Smart mode breaks the entity tag into a per-field tag set. Listings carry product-X.name + product-X.price + product-X.coverImage; detail pages carry the full set; buybox carries product-X.price + product-X.deliveryTime + product-X.stock. A description-only change matches only the detail page’s tag set, so only that one entry is purged.

Changed field on a productSmart invalidates
nameDetail + listings (name shown in cards) + category pages (referenced in breadcrumb associations)
descriptionDetail only
priceDetail + listings + buybox + home (if featured)
stockDetail + buybox
deliveryTimeBuybox only
coverId (cover image)Detail + listings
metaTitle / metaDescription / keywordsDetail only
categoryIds (assignment change)Detail + every old & new category page + listings
activeDetail + listings + category pages
properties (assignment)Detail + filter aggregations
visibilities (sales-channel assignment)Detail + listings + category pages in affected channels
Changed field on a categorySmart invalidates
nameCategory page + parent listings + navigation menus
descriptionCategory page only
parentId (move)Old & new category trees + navigation menus
activeWhole tree under it
productAssignmentType / productStreamIdCategory page + listings
Changed field on a CMS pageSmart invalidates
name / sections / slotsThe CMS page entry
Assignment to a categoryThe category page + the CMS page

Custom fields are bucketed conservatively — they invalidate the detail page plus listings if the custom field appears in a property block typically shown on cards.

If you have a custom field that controls only the detail page output (e.g. a “warranty” rich-text block), Smart still treats it as listing-affecting by default, to be safe. Override the mapping if you know better — see the Extending Smart section below.

When Smart over-purges (and when it doesn’t)

Section titled “When Smart over-purges (and when it doesn’t)”

Smart is conservative. When in doubt, it purges more rather than risk leaving a stale page. Cases where it deliberately over-purges:

  • Bulk product import via DAL — Shopware fires write events with a single “everything was set” payload. Smart can’t tell which fields effectively changed and purges everything.
  • First save after a migration — same reason as above.
  • A non-tracked field whose value matters — e.g. you added a Twig macro to your theme that reads a non-tracked custom field. Smart doesn’t know your theme reads it, so it won’t purge listings when that field changes.

For the first two, expect a one-off large purge after big imports. For the third, switch to Precise or Extended for that one save, or add a manual purge from your import script.

  • You run a content site, not a shop — content rarely changes; the over-purges from Precise / Extended aren’t worth the analysis overhead.
  • You always do bulk changes — Smart and Precise will both purge most of the cache on bulk imports anyway; pick whichever produces less framework overhead during the analysis pass.
  • Your storefront is heavily personalised — most pages are bypassed anyway; the simpler modes are fine.

The field-diff is computed inside the entity-written event handler. For a single-product save, it adds sub-millisecond overhead. For bulk updates, the overhead scales linearly with the number of entities — usually negligible compared to the database write itself, but visible in worst-case profiles.

If the analysis becomes a bottleneck on very large imports, switch to Precise for the duration of the import and back to Smart afterwards.

Smart’s field mapping lives in SmartInvalidationAnalyzer. To extend it from a custom plugin:

  1. Decorate P2Lab\Cache\Service\SmartInvalidationAnalyzer with your own implementation.
  2. Override the analyze<Entity>Change(array $changedFields): array methods to return your custom tag set for fields the plugin doesn’t know about.

The standard tag conventions are documented in Architecture.