Three causes cover nearly everything
When we take over a slow TYPO3 installation, the finding is rarely exotic. It is nearly always one of three things: the page does not come from the cache, images go out at their original size, or every page loads code that only one page needs.
All three are easy to find once you know where to look, and all three are configuration questions rather than rebuilding projects. So the work starts with a measurement, not with an estimate.
The page cache is the biggest lever
TYPO3 stores the finished page and serves it directly on the next request. That is the single most important reason a TYPO3 site can be fast, and the most common place where speed goes missing.
The cache is easy to defeat: a content element that deliberately renders uncached, a plugin that recalculates its output on every request, an extension that starts a session and thereby personalises the page for everyone. The effect does not show during development, because development runs without the cache anyway. It does not show in testing either. It shows when traffic arrives.
So we look first at which pages are being cached at all and which element is preventing it. Often it is exactly one, and often it can be rebuilt so that only the dynamic part stays uncached instead of the whole page. What sits behind this is described in the glossary under caching.
Images: not smaller, but right
The TYPO3 file handling converts images into the sizes actually needed and stores the results. That works well once configured, and not at all when the template outputs the original file.
We check three things here: whether conversion happens at all, whether modern formats go out, and whether every image carries width and height in the markup. The last point has nothing to do with file size and is often the most visible one: without dimensions the browser does not know how much space to reserve, and the layout jumps while the page loads. That is exactly what Google measures as layout shift.
What loads on which page
The third classic is assets included globally through TypoScript. A carousel script only the home page needs. A stylesheet for a form that appears on a single subpage. An icon set of which three symbols are used.
This does not come from carelessness but because including something globally is the shorter route and bothers nobody while building. Clearing it up means finding out what is genuinely used and moving the rest to where it belongs.
Measuring, and measuring properly
In optimisation work, the measurement is the actual job. Measure two variants one after the other and a substantial part of what you measure is the daily form of the machine you measure on.
So we work like this. The baseline is taken on Google’s infrastructure, not on a development machine. Comparisons between two states run interleaved, A, B, A, B, across several passes, and the median is what counts. Measured in blocks, every load fluctuation of the machine moves straight into the comparison and you end up optimising against noise.
It sounds laborious and it is the difference between a demonstrated improvement and a claimed one.
What happens afterwards
An optimisation is a date, not a state. Content grows, extensions get updates, and at some point somebody adds a script for a campaign and never removes it.
For that to surface before anyone reports it, an ongoing measurement belongs to the job. We use SiteSentry for it, the free tool from aceArt GmbH: it measures at regular intervals through Google’s official interface and gets in touch when a value drops below your threshold.