baldinof/roadrunner-bundle
Symfony bundle that integrates the RoadRunner high-performance PHP application server, providing an easily configurable, extendable worker with middleware support, kernel reboots, and out-of-the-box integrations for Sentry, sessions, Doctrine, Blackfire, and Xdebug.
Architecture fit
Baldinof\RoadRunnerBundle\BaldinofRoadRunnerBundle, a Symfony kernel bundle plus a Runtime entrypoint wired via APP_RUNTIME. It cannot be dropped into a Laravel application; Laravel's equivalent is first-party (laravel/octane with --server=roadrunner), which solves the same problem set (worker bootstrapping, per-request container reset, long-lived process safety).ResetInterface on stateful services, integration shims for Doctrine/Sentry/sessions) map almost 1:1 onto Octane's sandbox and listener model, making it a useful checklist for what Octane must be validated against..rr.yaml. Any evaluation must treat the bundle + binary + config as one deployable unit.Integration feasibility
composer require, optional Flex recipe, copy .rr.* configs, pull the binary with spiral/roadrunner-cli, run bin/rr serve. No application code changes required to boot; correctness work begins at state hygiene.nyholm/psr7 or diactoros, typically via symfony/psr-http-message-bridge); changelog shows a DI misconfiguration when sensio/framework-extra-bundle is present without nyholm/psr7. This is a known sharp edge worth pre-empting in the base image.Kernel::handle() and are resolved once at worker start. That constrains their use to transport/response-shaping concerns, not application logic, and makes initialization cost a startup-time concern rather than per-request.Technical risk
2.0.0 release notes), while current RoadRunner releases use year-based versioning. rr get pulls latest by default, so an unpinned binary can silently outrun the bundle's relay/RPC protocol assumptions. Mitigation: pin the exact binary version in the Docker image and CI, and treat binary upgrades as bundle upgrades.StreamedResponseListener firing early (1.2.2), Basic Auth server vars unpopulated (1.0.2). Each was fixed, but the pattern tells you the regression surface is ongoing, not closed.on_exception with an allowed_exceptions allowlist is the default-efficiency path but requires the team to correctly classify which exceptions leave services in a recoverable state. Misclassification produces intermittent, hard-to-reproduce corruption in long-lived workers.ResetInterface must be implemented on anything holding per-request state; the bundle will not detect omissions.Key questions
composer.lock, especially DBAL 3.x (fixed in 2.1.1) and Symfony 6 (2.1.2).ResetInterface? This is the single largest unestimated work item.Stack fit
cache.adapter.roadrunner.kv_<name>), and Prometheus metrics declared in Symfony config and scraped from the RoadRunner endpoint. These are the levers that make the migration a platform change rather than a server swap.Migration path
.rr.yaml to a single bounded service in dev, exercise the dev config (.rr.dev.yaml auto-reload); (3) fix state hygiene findings; (4) canary in production behind weighted routing; (5) widen by service.rr get-binary --location /usr/local/bin) but with an explicit version flag rather than latest.Compatibility
nyholm/psr7 given the documented conflict with sensio/framework-extra-bundle when it is absent..rr.dev.yaml reload config and VarDumper caveat (dumps go to bin/console server:dump or the profiler, not the response body) should be written into the onboarding doc, or the first sprint will be spent rediscovering it.Sequencing
ResetInterface status. Deliverable: go/no-go with measured baseline deltas.ResetInterface where missing; classify exceptions into the allowed_exceptions allowlist; decide the reboot strategy (start conservative with always or on_exception with a narrow allowlist, then relax).Maintenance
Support
WorkerStartEvent, WorkerStopEvent, WorkerExceptionEvent, WorkerKernelRebootedEvent) are the supported extension points for operational hooks — use them for metrics, log correlation, and alerting rather than patching internals (Worker is marked internal as of 1.3.0).Scaling
memory reboot strategy (threshold in MB, default 128) is the built-in guard against slow leaks; max_jobs (with max_jobs_dispersion, e.g. 0.2, to avoid synchronized restarts) is the guard against cumulative drift. Combining [on_exception, max_jobs, memory] is the recommended production posture for a first cut — it trades a small amount of throughput for predictability.Failure modes
ResetInterface audit, and integration tests that deliberately throw and then assert clean state on the next request.memory strategy plus container memory limits plus OOM alerting.rr get. Mitigation: pin, and fail the build on mismatch.max_jobs_dispersion is omitted, all workers reboot together and capacity momentarily collapses; always set dispersion.Ramp-up
How can I help you explore Laravel packages today?