Installation
Requirements
Minimum, as declared in composer.:
- PHP 8.1 or newer
- TYPO3
^12.4 || ^13.0 || ^14.0 typo3/cms-schedulerandtypo3/cms-reports, both pulled in as dependencies
Database
- Four indexes are added through
ext_, two ontables. sql pagesand two ontt_content; run the database compare after installing - No tables and no columns are added — the extension reads the standard
starttimeandendtimefields
Compatibility
The combinations below are the ones the CI matrix in
.github/ builds.
| TYPO3 version | PHP version | Status | Notes |
|---|---|---|---|
| 12.4+ | 8.1 - 8.4 | ✅ Supported | PHP 8.5 is excluded from this cell in CI |
| 13.0+ | 8.2 - 8.5 | ✅ Supported | PHP 8.1 is excluded from this cell in CI |
| 14.0+ | 8.3 - 8.5 | ✅ Supported | PHP 8.1 and 8.2 are excluded from this cell in CI |
| 11.5 | — | ⚠️ Not supported | Below the typo3/cms-core: ^12.4 requirement |
Installation methods
Method 1: Composer (recommended)
composer require netresearch/nr-temporal-cache
vendor/bin/typo3 extension:setup
vendor/bin/typo3 cache:flush
extension: performs the database migrations, which is what creates
the four indexes.
Method 2: TER (Extension Repository)
- Go to Admin Tools → Extensions
- Click Get Extensions
- Search for
nr_temporal_cache - Click Import and Install
- Activate the extension
Method 3: Manual installation
- Download from GitHub
- Extract to
typo3conf/(classic mode) orext/ nr_ temporal_ cache/ packages/(Composer mode)nr_ temporal_ cache/ - Activate in the Extension Manager
- Clear all caches
Configuration
Zero configuration
The extension works immediately after installation. It automatically:
- Registers the PSR-14 listener for
ModifyCacheLifetimeForPageEventunder the identifiertemporal-cache/modify-cache-lifetime - Monitors the
pagesandtt_contenttables - Caps the page cache lifetime at the next transition, using global scoping and dynamic timing
All twelve settings and their defaults are listed in Configuration.
Optional: Monitor custom tables
If you have custom extension tables with starttime/endtime fields, you can
register them for temporal cache monitoring using the TemporalMonitorRegistry.
Recommended: Configure in Configuration/Services.yaml (modern dependency injection):
services:
# Register custom news table
my_ext_news_table_registration:
class: 'Closure'
factory: ['@Netresearch\TemporalCache\Service\TemporalMonitorRegistry', 'registerTable']
arguments:
- 'tx_news_domain_model_news'
- ['uid', 'pid', 'title', 'starttime', 'endtime', 'hidden', 'deleted', 'sys_language_uid']
# Register custom event table
my_ext_events_table_registration:
class: 'Closure'
factory: ['@Netresearch\TemporalCache\Service\TemporalMonitorRegistry', 'registerTable']
arguments:
- 'tx_events_domain_model_event'
- ['uid', 'pid', 'title', 'starttime', 'endtime', 'hidden', 'deleted', 'sys_language_uid']
Alternative: For ext_localconf.php (when DI not available):
<?php
use Netresearch\TemporalCache\Service\TemporalMonitorRegistry;
use TYPO3\CMS\Core\Utility\GeneralUtility;
// Only use makeInstance() in ext_localconf.php where DI is not yet available
$registry = GeneralUtility::makeInstance(TemporalMonitorRegistry::class);
$registry->registerTable('tx_news_domain_model_news', [
'uid', 'pid', 'title', 'starttime', 'endtime', 'hidden', 'deleted', 'sys_language_uid'
]);
Field requirements
registerTable() rejects a registration that misses one of these:
uidstarttimeendtime
Recommended in addition, because the queries and the backend module use them:
pid— parent page idhiddenanddeleted— the transition queries exclude records whose TCAdeleteandenablecolumns.disabledfields are setsys_language_uid— the queries filter on the language of the context- a label field such as
title,headerornamefor display
Passing an empty field list applies the default list
uid, pid, title, starttime, endtime, hidden, deleted, sys_language_uid.
Default tables
pages and tt_content are monitored out of the box.
Re-registering either of them throws an exception.
Each registered table adds two MIN() queries to a transition lookup — see
High database load.
Optional: Adjust the maximum lifetime
advanced.default_max_lifetime caps the cache lifetime the extension
calculates, and is the lifetime used when no transition is scheduled at all.
Default: 86400 seconds (24 hours)
Configure it in Admin Tools → Extensions → nr_temporal_cache → Configure, under Default Cache Lifetime (seconds), or in PHP:
<?php
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['nr_temporal_cache']['advanced']['default_max_lifetime'] = 43200;
TypoScript config.cache_period takes precedence over this setting; see
Advanced options.
Verification
Check the setup
vendor/bin/typo3 temporalcache:verify
The command confirms that the indexes and the columns the queries rely on exist, and that the configured strategy names are valid. System → Reports → Temporal Cache shows the same configuration from the backend.
Test scheduled content
-
Create a test page:
- Set Start to 5 minutes in the future
- Enable In menu
- Save
- Check the frontend menu — the page must not appear yet
- Wait until the start time and reload — the page appears without any cache being cleared by hand
The page cache lifetime is capped at the transition, so the first request after the start time regenerates the page.
Test expiring content
- Create a content element with Stop 5 minutes in the future
- View the page — the element is visible
- Wait until the stop time and reload — the element is gone
Inspect what the extension calculated
advanced.debug_logging = 1
Each page cache generation then logs the lifetime that was written, the uncapped value, and which maximum applied. See Advanced options.
Troubleshooting
Content does not update
-
Confirm the extension is loaded:
vendor/bin/typo3 extension:listCopied! - Confirm the timing strategy.
scheduleralways depends on the scheduler task, andhybriddoes when at least one oftiming.hybrid.pagesandtiming.hybrid.contentis set toscheduler. In those cases confirm the task exists and cron is running it — see Scheduler task. Ahybridconfiguration with both rules ondynamicneeds no task. -
Clear all caches:
vendor/bin/typo3 cache:flushCopied! - Work through Troubleshooting
Slow page generation
The dynamic timing strategy runs two MIN() queries per monitored table on
every page cache generation.
Confirm the indexes exist:
SHOW INDEX FROM pages WHERE Key_name LIKE 'idx_temporalcache%';
SHOW INDEX FROM tt_content WHERE Key_name LIKE 'idx_temporalcache%';
If they are missing, run the database compare — the definitions ship with the extension:
vendor/bin/typo3 extension:setup
To log the extension's own messages into a separate file:
<?php
$GLOBALS['TYPO3_CONF_VARS']['LOG']['Netresearch']['TemporalCache']['writerConfiguration'] = [
\TYPO3\CMS\Core\Log\LogLevel::DEBUG => [
\TYPO3\CMS\Core\Log\Writer\FileWriter::class => [
'logFile' => 'typo3temp/var/log/temporal_cache.log',
],
],
];
Workspace and language
Every transition query resolves the workspace and the language from the
Context API and filters on both.
A transition scheduled in another language therefore does not shorten the
lifetime of the page you are looking at.
Uninstallation
The extension adds no tables and no columns.
It does add four indexes to pages and tt_content
(idx_temporalcache_starttime and idx_temporalcache_endtime, see
ext_); remove them in Admin Tools → Maintenance →
Analyze Database Structure after uninstalling if you do not want to keep them.
composer remove netresearch/nr-temporal-cache
vendor/bin/typo3 cache:flush
TYPO3 then reverts to its default behaviour: temporal content becomes visible when the page cache happens to expire.
Next steps
- Configuration - Every setting and its default
- Architecture - How the listener, strategies and repository fit together
- GitHub issues - Report problems