TYPO3 on FrankenPHP: Operational Gotchas
FrankenPHP's worker model is fast and lovely — and it quietly changes your mental model for config reloads, logging, and deploys versus classic PHP-FPM. Part 4 of "The Ops Log."
TL;DR
TL;DR: The worker is frontend-only, so backend requests run as classic PHP and pick up config edits in ~2s — but a code change to a preloaded class needs the process restarted. TYPO3 file logging is effectively dead over HTTP; route logs to stderr. And /app is an emptyDir — in-pod edits vanish on recreation.
What happened
Gotcha 1 — two runtimes in one pod. The FrankenPHP worker serves the frontend; a request classifier 503s backend/install requests out of the worker, so /typo3, /login and the whole auth chain run as classic PHP with a fresh bootstrap per request. Practical upshot: with opcache.validate_timestamps=On, editing additional.php or a non-preloaded extension class takes effect within ~2s — no pod restart. Great for hotfixing config.
Gotcha 2 — preload pins classes, so some swaps need a restart. The flip side of gotcha 1: opcache.preload pins the TYPO3\CMS\* core into the process at boot. Swap the code of a preloaded class under a running worker and you get a duplicate-class TypeError — the old definition is still pinned. Those deploys must restart the FrankenPHP process, not just drop new files:
what "takes effect" depends on what changed
no restart additional.php, non-preloaded ext class (validate_timestamps=On)
restart anything under opcache.preload (TYPO3\CMS\*)
restart class signature swaps → duplicate-class TypeError
Gotcha 3 — file logging is a black hole over HTTP. The log writer config points at a path the CLI warmup can write but the HTTP worker's working directory can't, so typo3_*.log sits at zero bytes and you debug blind. The way out is to route a channel to PhpErrorLogWriter, whose error_log goes to /dev/stderr — which is exactly what kubectl logs reads:
additional.php — make logs visible
$GLOBALS['TYPO3_CONF_VARS']['LOG'][$vendor][$ext]['writerConfiguration']
[\Psr\Log\LogLevel::DEBUG]
[\TYPO3\CMS\Core\Log\Writer\PhpErrorLogWriter::class] = [];
$ kubectl -n kunde-xyz logs <pod> -c app # ← now the channel shows up</pod>
Gotcha 4 — /app is ephemeral. The application directory is an emptyDir repopulated by init containers (an OCI artifact pull plus setup) on every pod start. Edit a file in the running pod to test something and it's gone the moment the pod recreates. Anything permanent goes through the build artifact and the deploy — the pod filesystem is a scratchpad, not a source of truth.
The lesson
Under FrankenPHP, "did my change take effect?" has three different answers depending on whether it's config, a preloaded class, or a file on disk. Know which one you're touching before you assume a restart is or isn't needed.
Frequently asked questions
Can I test hotfixes directly in the running pod?+
Not permanently — /app is an emptyDir repopulated by init containers on every pod restart. In-pod edits are a scratchpad for short-lived tests, not a place for permanent changes.
Why are TYPO3 log files empty?+
Because the log writer points at a path the HTTP worker can't write to, even though the CLI warmup could. The fix is to route a channel to PhpErrorLogWriter, which writes to stderr.
How do I know whether a deploy needs a restart?+
Check whether the changed class is pinned under opcache.preload (typically TYPO3\CMS\* core classes) or whether a class signature changed — in both cases a process restart is needed, not just new files.
Why do backend changes take effect faster than frontend changes?+
Because the FrankenPHP worker only serves the frontend — backend/install requests run as classic PHP with a fresh bootstrap per request, so opcache.validate_timestamps works normally.
Conclusion
FrankenPHP's worker model is a genuine operational win — faster requests, less overhead — but it splits what "needs a restart" means across three different places: config, preload, and the filesystem. If you don't keep those three cases apart, you either debug blind or restart unnecessarily.
I run and harden your TYPO3 platform on FrankenPHP — including the operational quirks classic PHP-FPM knowledge doesn't cover.
From worker architecture through preload strategy to logging and the deploy pipeline: I build TYPO3-on-FrankenPHP setups that stay predictable in production.
Platform operations, not consulting on paper: I build and maintain your TYPO3 platforms on an ongoing basis.
About the author
![[Translate to English:] Foto von Kai Ole Hartwig.](/fileadmin/_processed_/e/9/csm_ole-neu_73323ad80d.jpeg)
Kai Ole Hartwig
Programming since 2002 – self-taught, set up my own business with KO-Web in 2012. Over 100 projects, with a focus on security, performance, automation and quality. Today freelance: DevSecOps consulting, training and software development.
