Approach, limits and a core solution
Important
ext_emconf.php declares version 0.9.0 and state beta.
v0.9.0 is the first stable release.
Overview
This chapter explains why the extension works the way it does, what the approach cannot do, and what a solution inside TYPO3 core would have to provide to make the extension unnecessary.
Nothing here describes committed work in TYPO3 core. There is no accepted RFC, no target version and no timeline for a core solution; treat the section on it as a description of the missing capability, not as a roadmap.
What the extension does today
TYPO3's cache API accepts a relative lifetime — "keep this for N seconds". It has no absolute expiration — "keep this until timestamp T". Temporal visibility is an absolute-expiration problem, so the extension approximates one in two ways.
- Shorten the lifetime (
timing.strategy = dynamic) - The listener on
ModifyCacheLifetimeForPageEventcomputesnextTransition - time()and sets that as the entry's lifetime.
public function __invoke(ModifyCacheLifetimeForPageEvent $event): void
{
$lifetime = $this->timingStrategy->getCacheLifetime($this->context, $event->getPageId());
if ($lifetime !== null) {
$maxLifetime = $this->determineMaxLifetime($event->getRenderingInstructions());
$event->setCacheLifetime(\min($lifetime, $maxLifetime));
}
}
- Flush tags from a scheduled task (
timing.strategy = scheduler) - The listener leaves the lifetime alone.
TemporalCacheSchedulerTaskasks for every transition since its last run and flushes the cache tags the scoping strategy names for each of them.
hybrid combines the two, choosing per record type.
See What each timing strategy does for the exact behavior of each strategy.
Properties of this approach
- Works with the released TYPO3 versions
^12.4 || ^13.0 || ^14.0, no core patch required.- Nothing to configure for it to work
- The defaults (global scoping, dynamic timing) are active on installation.
- Runs queries on every page cache write
- With
dynamictiming, each write costs twoMIN()queries per monitored table — four with the defaultpages/tt_contentpair.schedulertiming moves that cost out of page generation entirely. - Cannot express per-entry absolute expiration
- The only lever is the relative lifetime of the entry currently being written, so an upcoming transition anywhere in the scope shortens the lifetime of the entry, whether or not that entry actually shows the affected record. This is why global scoping expires all page caches at every transition.
- Cannot follow arbitrary dependencies
- With
dynamictiming,per-pagescoping does not see content embedded from another page throughCONTENT/RECORDS, andper-contentscoping narrows only the flush tags, not the lifetime.
What a core solution would need
Two capabilities are missing from TYPO3, and both would have to come from core.
Absolute expiration in the cache API
A cache entry would have to be able to carry an absolute expiry timestamp alongside its relative lifetime, so the frontend could say "this entry is valid until 2026-10-28 14:30" without a background job and without shortening anything else.
With that, the extension's work would reduce to attaching the transition timestamp of the records that were actually rendered — per entry, with no site-wide lookup and no scheduler.
Temporal dependency tracking
The deeper gap is that nothing records which temporal records contributed to a cache entry. If the rendering pipeline tracked that — the way cache tags already track record identity — the expiry timestamp could be derived automatically and correctly, including for content embedded across pages, which is exactly the case this extension cannot cover.
That is a change to the rendering pipeline, not to the cache API alone.
If core gains these capabilities
Nothing in this extension currently detects core capabilities or switches APIs automatically; that would have to be built when there is an API to build against.
What would happen in practice:
- The extension would gain support for the new API on the TYPO3 versions that have it, keeping the current implementation for the versions that do not.
- Once every supported TYPO3 version carried the core solution, the extension would have nothing left to do and could be removed from a project.
Until then, the settings described in Configuration are the only lever.
When this approach fits
- It fits when
- Temporal content exists and stale menus or stale content elements are a real editorial problem; and the cache behavior of the chosen configuration has been measured on the site in question.
- It does not fit when
- No record uses
starttime/endtime— the extension then only adds queries; or the site cannot absorb the cache churn of the configuration it needs and no scoping/timing combination brings it down far enough.
Both cases are judgment calls about a specific site. Decision guide walks through which configuration matches which shape of site, and Alternative approaches covers approaches that do not involve this extension.
Feedback
The interesting feedback for this problem is the concrete behavior of a real site: which scoping and timing combination was chosen, and what happened to the cache hit ratio.
- Forge #14277 — the core issue
- Issue tracker — bugs and feature requests for this extension