Automatic page cache clearing on Extbase record changes
When your plugin persists a change through a repository, the pages that display that record are already in the page cache and would keep serving the old content until their cache expired. Extbase prevents that: after a repository write, it clears the cache of the pages affected by the change. This is the default behaviour, and the write-side counterpart to the read-side cache tags of the previous page.
On this page
How an Extbase repository write clears the cache
Three repository operations trigger cache clearing: adding, updating and
removing a record. Each
INSERT,
UPDATE and
DELETE that goes
through the Extbase persistence layer registers the affected record — its table
and UID —
for later clearing. At the end of the request, Extbase resolves the
registered records to page UIDs and flushes the page cache for those pages.
Two details are worth knowing:
- Clearing happens at the end of the request, not the instant you call
addor() update. Several writes in one request are collected and their pages flushed together once.() - Registration is driven by records, not relations. A write that only touches a relation (MM) table — with no record of its own — does not register a record for clearing.
Which pages an Extbase record change clears
For each changed record, Extbase clears three kinds of page:
- Every page tagged with that record. This is the primary mechanism and the
reverse of cache tags. When a page renders
a record, its cache entry is tagged with
<table>_<uid>. When that record changes, Extbase flushes the<table>_<uid>tag, which invalidates every page carrying it. A conference shown on ten different list pages is therefore refreshed on all ten when it changes — without anyone configuring which pages those are. The storage page below is not how a list page gets cleared; the tag is. - The record's storage page — additionally, the page whose
pidthe record lives on is flushed (by itspagetag). This has no effect if the storagePid is a sysFolder, but for a content bearing page type it makes a difference. Consider the impact before deciding where a record stores as to not invalidate page caches for pages that might not even display that record.Id_<pid> - Any pages named in that page's TCEMAIN.clearCacheCmd Page TSconfig. An integrator can name further page UIDs to flush whenever any record on the storage page changes. Unlike the per-record tag above, this is a coarse, page-level rule the integrator maintains by hand — useful when a page depends on the storage folder as a whole rather than on one record.
The page cache lifetime and where it comes from
Automatic clearing flushes a page early, when its records change. Absent any change, a cached page lives until its lifetime expires. That lifetime is not a single fixed number — it is resolved from several sources, each overriding or narrowing the previous:
- The page's Cache timeout field (Page > Behaviour > Cache timeout). If set to a non-zero value, it wins.
- TypoScript
config.. Used when the page field is not set.cache_ period - A framework fallback when neither of the above applies. In the calculator that handles record and page lifetimes this fallback is one year; a separate 24-hour fallback applies to the content-object rendering path. Treat these as innermost fallbacks, not as "the" default.
- Narrowed by record visibility. The lifetime is then shortened to the next
starttimeorendtimeof the records on the page, so a page expires no later than the moment its content becomes visible or hidden. - Overridden by an event. Finally, a listener on ModifyCacheLifetimeForPageEvent receives the resolved value and may replace it entirely.
Because of this chain, do not rely on a hard-coded number for "how long a page is cached". If you need the real, effective value for a given page, verify it rather than infer it:
- Inspect the cache entry. With the default database cache backend, the
cache_table stores anpages expirestimestamp for each cached page. The remaining lifetime isexpiresminus the current time. - Observe the resolved value. A listener on ModifyCacheLifetimeForPageEvent is handed the fully resolved lifetime for the page; logging it there reports exactly what the system computed, after every source above has been applied.
The enableAutomaticCacheClearing setting for Extbase
Automatic clearing is controlled by
config., which is
enabled by default:
config.tx_extbase {
persistence {
# On by default. Set to 0 to stop repository writes from clearing
# the page cache automatically.
enableAutomaticCacheClearing = 1
}
}
The setting gates the flush, not the registration: repository writes always register their changed records, and the setting decides whether those registered pages are cleared at the end of the request.
This is a global TypoScript setting in
config.. It
applies to every repository write on the site for as long as it is set, and there
is no supported way to toggle it temporarily from PHP for a single operation —
unlike
\TYPO3\, whose runtime behaviour
can be adjusted per instance. Setting it to
0 therefore means every
repository write across the site stops refreshing the frontend, and clearing
caches becomes your own responsibility through the
cache-clearing helper. Leave it at its
default unless a deliberate, site-wide cache strategy replaces it.
What automatic Extbase cache clearing does not cover
This mechanism is Extbase's own, and it only reacts to writes made through an Extbase repository. It does not cover:
- Raw database writes — records changed with a
DBAL
\TYPO3\query bypass the Extbase persistence layer, register nothing, and clear no cache. After such a write you must clear the affected pages yourself with the cache-clearing helper.CMS\ Core\ Database\ Query\ Query Builder - Relation-only changes — as noted above, a write that only touches an MM table registers no record.
- Caches outside the pages group — automatic clearing flushes by tag
within the
pagescache group, callingflushon every cache registered in that group, not only the page cache itself. A custom cache is reached by this if you register it into theBy Tags () pagesgroup and tag its entries with the same<table>_<uid>value — which is exactly what you want for a cache that stores rendered output, so it is invalidated together with the page cache. A custom cache left in the defaultallgroup is not in the pages group and is not touched, so you must invalidate it yourself. The two-level list cache from the optimisation section uses the pages group for precisely this reason.
\TYPO3\ is a different case: it is not
covered by this mechanism, but it clears caches on its own. A DataHandler write
registers the changed record for page-cache clearing through its own routine and
honours the same TCEMAIN.clearCacheCmd Page TSconfig — so records
written through DataHandler do refresh the frontend, just not via the Extbase path
described here.
With this, you have the full caching picture for an Extbase plugin: cached by default, non-cacheable only when you must, invalidated precisely with cache tags, and refreshed automatically when records change.
See also
- Caching for Extbase plugins — the chapter overview.
- Cache tags for Extbase plugins — the read-side counterpart: tagging pages so they can be invalidated.