symfony/runtime
Symfony Runtime decouples PHP applications from global state by handling environment, input, output, and exit through a front controller. It simplifies bootstrapping, makes code more testable, and supports multiple runtimes and frameworks.
Architecture fit
symfony/runtime occupies exactly the same architectural seam as Laravel's front controller: public/index.php → resolve environment → build the application → handle a request → emit a response → terminate. The component formalises that seam as two small contracts — RuntimeInterface (produce an application + resolve env/APP_DEBUG/options) and RunnerInterface (drive the application and return an exit code) — with GenericRuntime, SymfonyRuntime, ClosureRunner, SymfonyRunner, and a ResolverInterface for auto-detection. That is a clean, well-bounded abstraction, and conceptually it is the right shape for decoupling bootstrap from a specific SAPI.
The fit with Laravel specifically is weaker than the pitch implies. SymfonyRuntime is hard-wired to Symfony's KernelInterface/HttpKernelInterface and Symfony\Component\Dotenv. Laravel ships Illuminate\Foundation\Application and Illuminate\Contracts\Http\Kernel, which are not Symfony\Component\HttpKernel\HttpKernelInterface implementations, and Laravel has its own Dotenv + config:cache pipeline. So this is not "wrap your app in one line." It is "author and own a custom RuntimeInterface + RunnerInterface adapter that bridges Runtime's env/dotenv resolution to Laravel's bootstrap, and then keep the two env pipelines from fighting." That adapter is the actual deliverable; the package is the substrate.
Integration feasibility
Feasible, moderate effort, and the surface area is genuinely small — a competent senior PHP engineer can produce a working LaravelRuntime + LaravelRunner in a day, and a production-grade one with tests in one to two sprints. Composer-wise it resolves cleanly: symfony/http-foundation and symfony/http-kernel are already in Laravel's tree, and symfony/runtime has no heavy transitive requirements. Laravel 11/12 pairing with symfony/runtime ^7.x is coherent; ^8.x requires PHP ≥ 8.4 and will constrain the fleet more than Laravel itself does.
The honest feasibility question is why. Laravel already solved "run this app under a different server model" with Octane (RoadRunner/Swoole/FrankenPHP workers), and Laravel 11 already slimmed and centralised bootstrap in bootstrap/app.php. A meaningful share of this package's value proposition for Laravel is therefore already delivered by a first-party, Laravel-native package with a Laravel support commitment.
Technical risk
$_SERVER, argv, and dotenv files on every single request in the application's most privileged code path. It carries two CVEs in its recent history: CVE-2024-50340 (reading argv on non-CLI SAPIs → env-var injection) and CVE-2026-46626 (a bypass of that patch, fixed by gating argv on $_SERVER). A small dependency with a large blast radius that has had a patch bypass is a governance item, not a footnote. It argues for pinning, prompt patch SLAs, and treating this file as security-sensitive code under review..env/APP_ENV/APP_DEBUG; Laravel also loads .env and can bake env into config:cache. Two resolvers with different precedence rules is a class of bugs that only manifests in staging/production and produces "works locally, wrong DB in prod" incidents.symfony/symfony monorepo via subtree split, so its supported PHP/Symfony matrix is driven by Symfony's roadmap, not Laravel's. Symfony 8's PHP ≥ 8.4 floor will eventually be a constraint we did not choose.Dependents: 0 and 743 stars on the split repo materially understate real adoption (it is a dependency of symfony/framework-bundle; essentially every Flex application has it). It is a metadata artifact of the subtree-split pattern, not a quality signal — but any automated scoring in our intake process (this one scored 31.6 against the field's 58.1 opportunity) will mis-rank it, and we should recognise that class of false negative rather than let a score decide.Key questions
SymfonyRuntime (and reshape Laravel to look Symfony-shaped) or GenericRuntime with a bespoke Laravel adapter? I would default hard to the latter.$_SERVER/$_ENV reads in our own middleware and service providers — the package enables that work; it does not perform it.Stack fit
Target Laravel 11/12 on PHP 8.2–8.4, Composer 2. Pair with symfony/runtime ^7.2 (PHP ≥ 8.2) and hold ^8.x until the fleet is on 8.4. Do not introduce it in the same release train as a Laravel major upgrade — both change bootstrap, and concurrent changes there produce incidents that are expensive to bisect. Verify the resolved dependency graph first: Laravel's symfony/* constraints set the ceiling, and Composer will pick a Runtime version for you if you let it.
Migration path
The critical design decision is reversibility. Keep public/index.php as a three-line shim whose only job is to delegate to our adapter; then rollback is a one-file revert with no dependency change.
App\Runtime\LaravelRuntime implements RuntimeInterface and App\Runtime\LaravelRunner implements RunnerInterface. Prove parity on one non-critical service: HTTP responses byte-identical, Artisan exit codes preserved, APP_ENV/APP_DEBUG resolution provably identical to Laravel's current behaviour under config:cache on and off.$_ENV/$_SERVER mutation from Runtime leaks into Laravel's config.artisan is lower risk than HTTP and validates the Runner abstraction under a different SAPI — a genuinely useful signal that the adapter is not HTTP-shaped.Compatibility
.env and Laravel reads from the resulting environment, or Laravel keeps Dotenv and Runtime is configured not to touch it. Do not leave this ambiguous — it is the highest-probability production defect in the whole integration.APP_RUNTIME env var becomes a new piece of operational configuration. Treat it as such: it belongs in the deployment manifest, not in a developer's .env, or it silently resolves to the wrong class in one environment.project_dir / APP_PROJECT_DIR configurability (added in 7.4/8.0) is useful for monorepo layouts but is another runtime-specific path assumption to validate against our deploy layout.Sequencing
Spike → parity harness → console → HTTP canary → broad rollout → optional worker evaluation. Each stage has an independent rollback. Realistic calendar estimate: 2–3 sprints to production confidence on HTTP for a single service team, plus the unglamorous follow-on work of actually removing $_SERVER/$_ENV reads from our middleware — which is where the stated benefit lives and which is scoped as application refactoring, not a package integration.
Maintenance
Maintenance burden is low in the dependency and moderate in the glue. Upstream is actively maintained with security backports across five branches (5.4 / 6.4 / 7.x / 8.x) — the CVE-2026-46626 fix shipped to all of them essentially simultaneously, which is the behaviour you want from a boot-path dependency. The public API is tiny and stable, so the probability of an upstream breaking change is low, and the codebase is small enough that forking or absorbing it is a realistic fallback if the subtree-split repo ever goes quiet. The recurring cost is ours: the Laravel adapter, its tests, and its documentation are first-party code we own indefinitely, including the symfony/* version-ceiling conversations at every Laravel upgrade.
Support Vendor-backed by the Symfony core team, MIT-licensed, but with no commercial SLA and no Laravel-specific support surface — the issue tracker is Symfony's monorepo, and a Laravel integration question is out of scope there. Effectively: upstream fixes bugs and CVEs in the generic component; we are the sole support organisation for the Laravel-shaped parts. That must be an explicit ownership assignment (platform team), not an implicit one.
Scaling Runtime is a portability lever, not a scaling lever — it does not change throughput, memory, or cold-start on its own. Any scaling story ("40% lower cloud cost", "3× better cold start") is a claim about FrankenPHP/RoadRunner/Bref, and those benefits are available via Octane without this package. If we adopt Runtime, we should adopt it for uniformity of bootstrap across SAPIs and for testability, and price the scaling benefits separately and only after benchmarking the first-party alternative.
Failure modes
set_exception_handler that emits a degraded response, and health checks that exercise the real entrypoint rather than a framework-internal route.APP_RUNTIME → class-not-found fatal at boot in one environment only. Mitigation: validate at deploy time, not first request; fail the release, not the request.config:cache producing wrong credentials or wrong feature flags in production while passing every test.argv/$_SERVER handling if a future 0-day lands and our patch pipeline is slow. Mitigation: Dependabot/Renovate on this package specifically, alerting (not nightly batching), and the ability to ship a front-controller-only hotfix without a full application release train.Ramp-up
Individual ramp-up is trivial — two contracts, one doc page, half a day for a senior engineer to read the entire component. The real ramp-up is organisational: the team must internalise where env resolution now happens, why the front controller shim exists, and the rollback procedure. Budget 1–2 sprints of engineering time including the parity harness and documentation, and expect the first incident to be an environment-resolution issue rather than a code defect. Recommend a written decision record capturing the target capability that justified adoption — so that twelve months from now, when someone asks why public/index.php is three lines of indirection into a Symfony package, the answer is on file rather than reconstructed.
How can I help you explore Laravel packages today?