Caching & AOT Compilation¶
This page owns build-time compilation and nothing else. The runtime
key-value cache an application reads and writes —
Psr\SimpleCache\CacheInterface, Redis-backed — is Redis. Those
two pages are the whole subject; there is no separate runtime-cache page
to look for, and the two caches share a word and nothing else.
In production, Kinetis boots from one build-time artifact,
.kinetis-cache/compiled.php, instead of reflecting the application on
every boot: routes, commands, middleware, event listeners, parameter
binding and validation plans, and each installed package’s discovery
data. Build it in the deploy step, ship it with the code, and start
workers against it.
APP_ENV¶
use Kinetis\Runtime\AppEnvironment;
$env = AppEnvironment::detect(); // reads getenv('APP_ENV')
APP_ENV=development php -S localhost:8080 public/index.php
Only the exact name development, ignoring case, selects Development.
An unset APP_ENV and every other name — a deployment’s own staging
included — is Production. Local development sets APP_ENV=development
explicitly — see .env.example at the project root, or Configuration for
loading it from a .env file automatically.
Kinetis\Runtime\HttpStartup reads this once per boot, and bin/kinetis
reads it again for the CLI. Development discovers from source on every
boot; production uses the artifact.
Build the artifact in the deploy step¶
php vendor/bin/kinetis build
# Compiled routes, MCP tools/resources, commands, and event listeners written to /app/.kinetis-cache/compiled.php
kinetis build compiles from the project’s source every time and
replaces the artifact. The published file is an output of the command,
never an input to it. Routes, commands, global middleware, event
listeners and package discovery data are found by namespace — see
CLI.
Before it writes, the command reconstructs the whole artifact through the same checks a boot applies. A section that fails them fails the command, publishes nothing, and leaves the previous artifact in place.
If the application uses Latte or Twig, follow the build with
php vendor/bin/kinetis views:warm. That command runs the normal
application bootstrap, clears only the selected adapter directory,
recursively compiles the configured view root, and fails on a template
compile error. It therefore needs the deployment’s complete environment,
unlike kinetis build. Pure PHP and development mode report zero work.
See Views for the complete contract.
Deploying a rebuilt artifact¶
The artifact is not invalidated automatically. Rerun kinetis build in
every deploy that changes routes, commands, listeners, middleware or DTO
shapes.
Build it before workers start. compiled.php belongs in the
immutable artifact or image a deployment ships — built by the CI job or
the image build, then read by workers that start against it. Nothing has
to be invalidated in that shape, because no process has seen the path
before.
kinetis build runs on the CLI, in its own process, and can clear only
that process’s OPcache. Under opcache.validate_timestamps=0 it cannot
make a same-path replacement visible to an FPM pool or a FrankenPHP
worker that is already serving — those keep the previous file’s opcodes
no matter how many times the command reports success. If you run build
against a live shared deployment, restart the serving pool or workers
afterwards; until then the new artifact is not guaranteed active. A
persistent worker needs that restart for a code change anyway (see
Runtime Adapters).
Without a build step¶
In production with no usable artifact, the first boot compiles in memory, serves from that result, and publishes it for later boots. Concurrent PHP-FPM workers racing on an empty cache directory each publish a complete artifact, never a partial one. An artifact that is missing, from an older format, or rejected on load is compiled and replaced the same way.
Once an artifact exists, live discovery never runs again: a new
controller, command, listener or #[AsGlobalMiddleware] class is not
seen until kinetis build runs.
A machine that cannot write the cache directory — a read-only mount, a full disk — still serves. Each boot compiles in memory and writes one line to the error log naming the artifact it could not publish, so a permanently unwritable directory is visible rather than silent.
Note
Pre-warming avoids one cost: the compile-and-write on whichever request arrives first. A cold deployment that compiles lazily is consistently slower than a pre-warmed one for exactly that request.
What changes without a rebuild¶
.env and process environment configuration take effect on the next
boot without rebuilding compiled.php (Configuration). The OpenAPI
document is generated in memory from the active route table, rather than
stored in the artifact (Routing & Validation). Latte and Twig view
adapters keep their generated templates in separate directories under
.kinetis-cache/views/ (Views).
The AOT artifact lists the artifact’s exact contents, file format, atomic publication and rejection behavior.
See also¶
CLI — how MCP tools/resources and commands are found by namespace, with no registration file for either.
Runtime Adapters — why the artifact matters most under PHP-FPM, which boots on every request.
Routing & Validation / Model Context Protocol (MCP) — the live behavior this precomputes; nothing about how routes, tools or DTOs are declared changes.
Redis — the runtime
Psr\SimpleCache\CacheInterfacecache, as above.Appendix: Runtime Reference — the artifact’s format and publication protocol.