Zum Inhalt springen
Shops & CMS

TYPO3-Performance: Caching und Ladezeit im Griff behalten

Wie der Seiten-Cache in TYPO3 arbeitet, welche Einstellungen ihn aushebeln und wie Cache-Hash, Backends und das Deployment die Ladezeit einer Seite bestimmen.

15 Min. Lesezeit TYPO3CachingLadezeit

TYPO3 liefert Seiten schnell aus, solange der Seiten-Cache greift. Sobald aber ein Plugin bei jedem Aufruf neu rendert, ein Kampagnenparameter den Cache-Hash verändert oder ein Release die Cache-Tabellen leert, wandert die Arbeit aus dem Speicher zurück in PHP und in die Datenbank. Dieser Beitrag ordnet ein, wo TYPO3-Installationen in den Felddaten stehen, welche Einstellungen den Seiten-Cache aushebeln, wie sich die Cache-Backends unterscheiden und warum der erste Aufruf nach einem Deployment der teuerste des Tages ist.

Das Wichtigste in Kürze

  • In den Felddaten des Web Almanac 2025 erreichen 79 Prozent der mobil gemessenen TYPO3-Seiten gute Core Web Vitals; der Unterbau trägt also, die Ausreißer entstehen in der eigenen Konfiguration.
  • Ein dynamisches Element nimmt der Seite nicht den Cache, config.no_cache = 1 dagegen schon: TYPO3 legt das gerenderte Ergebnis dann gar nicht mehr ab und baut jede Anfrage komplett neu auf.
  • In den Cache-Hash gehen standardmäßig elf Angaben ein; jeder zusätzliche Parameter in der URL erzeugt eine weitere Kopie derselben Seite und verwässert die Trefferquote.
  • Das Datenbank-Backend ist die Voreinstellung und räumt nicht von selbst auf: ohne Scheduler-Aufgabe wachsen die Cache-Tabellen, bis der Cache-Zugriff selbst zur Bremse wird.
  • Nach einem Deployment sind die Caches leer, und der erste Aufruf blockiert wegen der Cache-Sperren weitere Anfragen; das Aufwärmen gehört auf das Live-System vor den Wechsel des Symlinks.
  • Ein voller Cache verkürzt die Serverzeit, nicht die Ladezeit im Browser: Bilder, Schriften und Fremdaufrufe bestimmen danach, wann die Seite nutzbar ist.

Wo TYPO3 im Feld steht

Der Web Almanac wertet für sein CMS-Kapitel Felddaten aus dem Crawl vom Juli 2025 aus. Von den mobil gemessenen TYPO3-Seiten erreichen darin 79 Prozent gute Core Web Vitals (Web Almanac 2025, Kapitel CMS, Abbildung 12.8). Beim Largest Contentful Paint liegt der Anteil bei 89 Prozent (Abbildung 12.9), bei Interaction to Next Paint bei 95 Prozent (Abbildung 12.11). Zum Vergleich: über alle mobil gemessenen Websites hinweg kamen 2025 62 Prozent auf einen guten LCP-Wert (Web Almanac 2025, Kapitel Performance, Abbildung 7.7). Beim LCP liegen mobil gemessene TYPO3-Seiten damit über dem Mobilschnitt des Datensatzes; die Schwellen, die in den Core Web Vitals 2026 gelten, erfüllen sie in dieser Messung also häufiger.

Über das eigene Projekt sagen diese Zahlen wenig. Sie beschreiben einen Bestand, in dem viele Installationen nah an den Voreinstellungen laufen: aktiver Seiten-Cache, wenige dynamische Bausteine, überschaubare Erweiterungen. Sobald ein Redaktionssystem über Jahre gewachsen ist, verschiebt sich das Bild. Ähnlich wie bei den häufigen Bremsen in WordPress-Installationen entstehen die Ausreißer selten im Kern, sondern in dem, was darum herum gebaut wurde: in einer Erweiterung, die pro Aufruf rendert, in einer URL-Struktur mit Kampagnenparametern, in einem Cache-Backend, das seit Jahren nicht aufgeräumt wurde. Der Unterschied zwischen einer flotten und einer trägen TYPO3-Seite liegt erfahrungsgemäß nicht in der Version, sondern in der Cache-Konfiguration.

Erst messen, dann schrauben

Vor jeder Änderung an der Cache-Konfiguration steht eine Messung mit und ohne Cache-Treffer. Ein Aufruf mit leerem Cache zeigt, was die Seite an Rechenzeit tatsächlich kostet; ein zweiter Aufruf zeigt, wie viel davon der Cache abnimmt. Erst die Differenz sagt, ob sich Arbeit am Rendering lohnt oder ob die Trefferquote das eigentliche Thema ist. Wer nur den warmen Aufruf misst, hält eine Installation für schnell, die es nur im Idealfall ist.

Der Seiten-Cache und was ihn abschaltet

TYPO3 speichert das gerenderte Ergebnis einer Seite und liefert es beim nächsten Aufruf aus dem Cache. Wie lange ein solcher Eintrag gilt, steuert config.cache_period; die Voreinstellung liegt bei 86.400 Sekunden, also 24 Stunden (TYPO3-TypoScript-Referenz, config). Ein Wert im Seitenfeld cache_timeout sticht die globale Einstellung, sobald er über null liegt. Kurze Lebensdauern sind dabei kein Widerspruch zum Caching: Die Core-API-Dokumentation hält ausdrücklich fest, dass selbst 30 Sekunden in manchen Szenarien schon etwas bringen. Für eine Übersichtsseite, die sich stündlich ändert, ist eine Minute Cache besser als gar keiner.

Der schnellste Weg, diesen Cache zu verlieren, ist config.no_cache = 1. Die Voreinstellung steht auf 0, und das aus gutem Grund: Mit 1 wird das Ergebnis gar nicht mehr im Seiten-Cache abgelegt (TYPO3-TypoScript-Referenz, config). Jede Anfrage durchläuft dann den vollen Aufbau aus TypoScript, Extbase, Fluid und Datenbankabfragen. In der Praxis landet die Einstellung oft in einer Bedingung, die einmal für eine einzelne Seite gedacht war und später global griff. Wer wissen will, was das kostet, misst die Zeit bis zum ersten Byte einmal mit und einmal ohne aktiven Cache-Treffer.

Die Dokumentation nennt den Ausweg direkt neben der Einstellung: Statt den Cache global abzuschalten, wird der dynamische Teil von USER auf USER_INT umgestellt, beziehungsweise COA auf COA_INT. TYPO3 holt dann den gecachten Teil der Seite aus dem Speicher und rendert anschließend nur die dynamischen Bereiche. Ein Suchformular, eine Anzeige des angemeldeten Namens oder ein Warenkorb-Kopf kostet damit einen Bruchteil dessen, was eine vollständig ungecachte Seite kostet. Der Preis dafür ist die Sorgfalt: Jeder dynamische Baustein läuft bei jedem Aufruf, auch bei dem des Suchmaschinen-Crawlers.

Zustand der SeiteWas im Seiten-Cache liegtWas pro Aufruf läuftAntwort-Kopfzeilen
Standardseite ohne dynamische Teilevollständige SeiteAuslieferung aus dem CacheCache-Control mit max-age
Seite mit USER_INT-Bausteingecachter Rahmennur die dynamischen BereicheCache-Control: private, no-store
config.no_cache = 1kein Eintragvollständiger SeitenaufbauCache-Control: private, no-store
Redakteur im Backend angemeldetEintrag bleibt bestehenAuslieferung aus dem CacheCache-Control: private, no-store

Welche Zeile für den eigenen Aufruf gilt, lässt sich nicht raten. TYPO3 schickt die Cache-Kopfzeilen nur, wenn vier Bedingungen gleichzeitig erfüllt sind: die Seite war gecacht, es liegen keine *_INT- oder *_EXT-Objekte auf der Seite, es ist kein Frontend-Benutzer angemeldet und es ist kein Backend-Benutzer angemeldet (TYPO3-TypoScript-Referenz, config.sendCacheHeaders). Andernfalls geht die Antwort mit Cache-Control: private, no-store heraus. Ein Redakteur, der die Seite im angemeldeten Zustand prüft, bekommt deshalb einen anderen Fall zu sehen als der Besucher. Wer genauer wissen will, wo die Zeit im Backend bleibt, hängt Server-Timing an die Antwort und trennt Datenbank, Rendering und Fremdaufrufe voneinander.

Cache-Hash: warum Parameter den Cache vervielfachen

Eine TYPO3-Adresse kann Parameter tragen, und jeder Parameter kann das Ergebnis verändern. Damit der Cache nicht die falsche Fassung ausliefert, bildet TYPO3 aus den relevanten Angaben einen Prüfwert, den Cache-Hash. In diesen Hash gehen laut Dokumentation standardmäßig elf Angaben ein, darunter die Seiten-ID, der Typ, die Gruppen-IDs, die Site, die dynamischen Argumente und die Zeilen der TypoScript-Vorlagen. Zwei Aufrufe mit unterschiedlichem Hash sind für den Cache zwei verschiedene Seiten. Was das für die Zahl der Einträge und für die Last auf der Datenbank bedeutet, zeigt sich spätestens dann, wenn ein Newsletter mit sechs Kampagnenparametern startet.

cachedParametersWhiteList

Nur die aufgeführten Parameter gehen in die Berechnung ein. Wirksam, aber scharf: Für jeden nicht genannten Parameter entfällt die Berechnung des Hashes vollständig.

requireCacheHashPresenceParameters

Legt fest, welche Parameter ohne Hash nicht akzeptiert werden. Damit lässt sich verhindern, dass fremd erzeugte Adressen ungeprüft in den Seitenaufbau laufen.

excludedParameters

Die genannten Parameter werden in der Berechnung ignoriert. Der übliche Platz für Kampagnenkennungen, die das Ergebnis der Seite nicht verändern.

excludedParametersIfEmpty

Zählt einen Parameter nur, wenn er auch einen Wert trägt. Nützlich bei Filtern, die das Formular auch ohne Auswahl mitschickt und die deshalb häufig leer bleiben.

excludeAllEmptyParameters

Wendet dieselbe Regel auf alle Parameter an. Eine Zeile statt einer Liste, dafür ohne Ausnahme für Parameter, deren leerer Zustand eine eigene Bedeutung hat.

enforceValidation

Prüft Adressen auch dann, wenn gar kein Hash übergeben wurde. Sinnvoll, wenn Parameter aus fremden Quellen kommen und der Cache nicht beliebig wachsen soll.

Die Optionen wirken nur, wenn sie zur tatsächlichen Adressstruktur passen. Ein Parameter, der die Ausgabe nicht verändert, gehört in die Ausschlussliste; bleibt er drin, legt jede Kampagne eine eigene Kopie jeder Landeseite an, und der Cache füllt sich mit Varianten, die niemand ein zweites Mal abruft. Umgekehrt darf ein Parameter, der die Ausgabe steuert, nicht ausgeschlossen werden: Dann liefert der Cache die Fassung des vorherigen Besuchers. Die Prüfung ist unspektakulär und schnell erledigt: Adressen aus dem Zugriffslog nach Parametern gruppieren, jede Gruppe einmal ansehen und entscheiden, ob der Parameter am Ergebnis etwas ändert.

Die Trefferquote ist die Kennzahl, nicht die Cachegröße

Eine große Cache-Tabelle ist kein Zeichen für gutes Caching, sondern häufig das Gegenteil: viele Einträge, die je einmal gelesen werden. Aussagekräftig ist der Anteil der Aufrufe, die aus dem Cache beantwortet werden. Wer diesen Anteil kennt, sieht sofort, ob eine Optimierung am Rendering überhaupt lohnt oder ob zuerst die Zahl der Varianten sinken muss.

Cache-Backends und Lebensdauern

Unter dem Seiten-Cache liegt das Caching-Framework mit mehreren Cache-Gruppen und je Gruppe einem Backend. Ohne eigene Konfiguration schreibt TYPO3 in die Datenbank: Das Datenbank-Backend ist laut Dokumentation die Voreinstellung, wenn kein Backend gesetzt wurde. Ein Eintrag ohne eigene Lebensdauer gilt dabei 3.600 Sekunden (TYPO3-Dokumentation, Caching-Backends). Diese Zahl betrifft nicht den Seiten-Cache, sondern die Vorgabe der Backends selbst; sie erklärt, warum ein selbst gesetzter Anwendungs-Cache nach einer Stunde wieder kalt ist, obwohl niemand ihn geleert hat. Wie sich die Schichten darüber verhalten, ist im Beitrag zu Varnish, Redis und Browser-Cache beschrieben.

Das Datenbank-Backend räumt nicht von selbst auf; die Dokumentation verweist dafür ausdrücklich auf die Scheduler-Aufgabe zur Garbage Collection. Fehlt diese Aufgabe, wachsen die Cache-Tabellen samt ihrer Tag-Tabellen weiter, und der Zugriff auf den Cache wird selbst zur Last. Für große Cache-Tabellen nennt die Dokumentation das Redis-Backend als Alternative, die den Datenbankserver entlastet. Der Wechsel ist eine Frage von wenigen Zeilen in der Systemkonfiguration; die Entscheidung, welche Gruppe umzieht, ist die eigentliche Arbeit. In welcher Reihenfolge die Schichten greifen, fasst unsere Seite zu Caching-Strategien zusammen.

config/system/additional.php
<?php

// Seiten-Cache in Redis halten und den Datenbankserver entlasten
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['pages'] = [
    'backend' => \TYPO3\CMS\Core\Cache\Backend\RedisBackend::class,
    'options' => [
        'database' => 3,
    ],
];

Das NullBackend gehört nicht auf das Live-System

Zum Entwickeln wird gern das NullBackend gesetzt, damit jede Änderung sofort sichtbar ist. Die TYPO3-Dokumentation ist an dieser Stelle deutlich und warnt davor, es produktiv einzusetzen, weil es das System erheblich verlangsamt. Auf einem Produktivsystem bedeutet die Einstellung: jeder Aufruf ohne einen einzigen Cache-Treffer, dauerhaft. Ein Blick in die Systemkonfiguration gehört deshalb in jede Abnahme, bevor eine Installation live geht.

Deployment: der erste Aufruf nach dem Wechsel

Nach einem Release sind die Caches leer. Die Dokumentation beschreibt die Folge nüchtern: Der erste Aufruf nach einem Deployment braucht in der Regel einen erheblichen Teil der Zeit und blockiert wegen der Cache-Sperren weitere Anfragen. Wer zur Hauptzeit ausrollt, verlagert damit einen Teil der Rechenarbeit auf die ersten echten Besucher, und das ausgerechnet in dem Moment, in dem am meisten Last anliegt. Wie viel Luft der Server für diesen Moment hat, hängt an der Serveroptimierung und an der Zahl der Prozesse, die parallel arbeiten können.

Das Aufwärmen gehört deshalb an eine bestimmte Stelle: laut Dokumentation auf das Live-System, in den Zielordner des neuen Release und idealerweise vor dem Umschalten des Symlinks. Caches, die auf einem Integrationsserver vorbereitet wurden, sind in der Regel wertlos, weil die Cache-Hashes dort nicht mit denen des Live-Systems übereinstimmen. Das Muster bleibt dasselbe: Systemgruppen aufwärmen, dann umschalten, dann den Seiten-Cache verwerfen. Wie viel PHP-Zeit der Aufbau tatsächlich kostet, zeigt ein Blick auf OPcache, JIT und die FPM-Worker.

deploy/release.sh
# Systemgruppen im neuen Release aufwärmen, bevor der Symlink umgelegt wird
cd /var/www/releases/2026-09-21
vendor/bin/typo3 cache:warmup --group system

# Erst danach auf das neue Release umschalten
ln -sfn /var/www/releases/2026-09-21 /var/www/current

# Seiten-Cache verwerfen, damit keine alten Fassungen weiterlaufen
cd /var/www/current
vendor/bin/typo3 cache:flush --group pages

Was neben dem Cache noch bremst

Ein voller Cache verkürzt die Serverzeit, nicht die Ladezeit im Browser. Sobald die Antwort in wenigen Millisekunden kommt, entscheiden Bilder, Schriften und Skripte darüber, wann die Seite nutzbar ist. Für Bilder aus der TYPO3-Dateiverwaltung heißt das: passende Größen statt eines Originals mit mehreren tausend Pixeln Breite, moderne Formate und feste Maße im Markup, damit beim Nachladen nichts springt. Die vollständige Kette vom Original bis zur ausgelieferten Datei geht der Beitrag zu WebP und AVIF durch.

  1. Die Trefferquote des Seiten-Caches über einen typischen Tag aufnehmen, getrennt nach angemeldeten und nicht angemeldeten Aufrufen.
  2. Alle Bausteine auflisten, die als USER_INT oder COA_INT laufen, und je Baustein prüfen, ob der dynamische Anteil wirklich dynamisch sein muss.
  3. Die Adressen aus dem Zugriffslog nach Parametern gruppieren und Kampagnenkennungen in die Ausschlussliste des Cache-Hashes aufnehmen.
  4. Die Scheduler-Aufgabe zur Garbage Collection einrichten und die Größe der Cache-Tabellen über mehrere Wochen beobachten.
  5. Das Aufwärmen der Systemgruppen in das Deployment aufnehmen und den Seiten-Cache erst nach dem Umschalten verwerfen.
  6. Nach jeder dieser Änderungen dieselbe Messung wiederholen, damit der Gewinn belegt ist und nicht behauptet.

Die zweite Gruppe von Bremsen sitzt hinter der Seite: Formularstrecken, Verfügbarkeitsabfragen, Preisberechnungen, Anbindungen an ein Warenwirtschaftssystem. Sie laufen häufig in einem dynamischen Baustein und damit bei jedem Aufruf, und sie bringen eine Laufzeit mit, die niemand im eigenen Haus kontrolliert. Wie sich Zeitüberschreitungen dort auf den Seitenaufbau auswirken und welche Absicherungen sich bewährt haben, steht im Beitrag zu Fremdsystemen im Seitenaufbau.

Eine TYPO3-Seite wird nicht dadurch schnell, dass ein Cache eingeschaltet ist. Sie wird schnell, wenn bekannt ist, welcher Anteil der Aufrufe ihn tatsächlich trifft - und was mit dem Rest passiert.

Projekterfahrung aus Performance-Projekten für Redaktionssysteme

Hinter einer Anmeldung verschwindet der Seiten-Cache ohnehin weitgehend. Dort zählt, was der Server je Aufruf leistet, und dort fällt jede unnötige Abfrage doppelt ins Gewicht, weil sie sich nicht mehr auf viele Besucher verteilt. Wie sich dieser Bereich messen lässt, ohne die Messung durch die Anmeldung selbst zu verfälschen, beschreibt der Beitrag zum Tempo hinter dem Login.

Dieser Artikel basiert auf Daten aus: Web Almanac 2025 (Kapitel CMS), TYPO3 TypoScript Reference (Top-Level-Objekt config) und TYPO3 Core API Reference (Caching-Framework, Backends und Konfiguration).

Verwandte Artikel

Frontend-Optimierung

Ungenutztes CSS finden und entfernen: schlanker laden

Wie viel CSS eine Seite braucht, wie sich der ungenutzte Anteil messen lässt und in welcher Reihenfolge sich Ballast ohne Darstellungsschäden entfernen lässt.

13 Min. Lesezeit
Server & Hosting

Weiterleitungsketten: die Ladebremse vor dem ersten Byte

Jede Weiterleitung kostet einen Roundtrip vor dem ersten Byte. So spüren Sie HTTP-, www- und Slug-Ketten auf und reduzieren sie auf einen einzigen Hop.

12 Min. Lesezeit
Server & Hosting

KI-Crawler-Last: Wenn Bots den Server ausbremsen

Bots erzeugen über die Hälfte der HTML-Anfragen. Warum KI-Crawler uncachebare Long-Tail-URLs treffen, wie Sie die Last messen und drosseln statt blocken.

14 Min. Lesezeit