bref/symfony-bridge
Bref runtime bridge for running Symfony on AWS Lambda. Install with Composer, extend BrefKernel in your Kernel, and deploy with a warm cache to reduce cold-start time. Avoid filesystem writes in production.
What it actually is. bref/symfony-bridge is not a platform; it is a thin glue layer (~a few hundred lines) between Symfony's Kernel and Bref's Lambda runtimes. Its surface area is three things: (1) a BrefKernel base class that overrides cache-directory handling for Lambda's ephemeral, largely read-only filesystem; (2) a Symfony Runtime adapter that lets Lambda invoke App\Kernel directly instead of going through public/index.php + PHP-FPM; and (3) a BrefSymfonyBridgeBundle that wires Bref's Monolog CloudWatch formatter (request-ID-prefixed log lines, Bref Cloud / Logs Insights correlation). 3.0.3 adds a fourth, small but real behaviour: per-request uploaded files left in /tmp are now deleted at the start of the next request. A TPM should evaluate it as a migration enabler, not as a dependency to be assessed on its own merits — the real platform decision is "Bref v3 + Lambda," and this package is the officially maintained Symfony on-ramp to it.
Architecture fit. Strong fit if the org is already on Symfony 5.2+ and is either (a) doing a lift-and-shift of a monolith toward serverless, or (b) running event-driven workers where Symfony Messenger is already the queue abstraction. The class-handler feature is the strategically interesting bit: it collapses the "write a separate bootstrap script per Lambda function" tax into "register a public service and point serverless.yml at the FQCN." That is a real reduction in per-function boilerplate as the number of event consumers grows. The FPM→function-runtime switch is a genuine architectural change (process reuse, BREF_LOOP_MAX, no shared memory between invocations, and — as 3.0.3 makes concrete — a /tmp that persists across requests and must be managed explicitly) and should be treated as such; it is not a config toggle to be flipped casually on a latency-sensitive HTTP app.
Integration feasibility. Low code effort, moderate operational effort. The README's own diff is one extends change; the rest is deploy-pipeline work: composer install --classmap-authoritative --no-dev --no-scripts, cache:clear --env=prod at build time, .env.local.php emission, and a decision on getWritableCacheDirectories(). The genuine friction is not the package — it is that every filesystem assumption in the app must be audited: cache pools, bundles writing to var/cache, temp-file usage, and now upload handling. 3.0.3 is a bug fix, not an API change — the upgrade itself is a patch bump — but it retroactively reveals that any app already running on the Bref runtime (not FPM) prior to 3.0.3 was silently accumulating request uploads in /tmp. For a typical mid-size Symfony app I would budget 3–5 engineer-days for the bridge itself and 2–4 engineer-weeks for the cache/filesystem/upload audit and warm-cache pipeline, depending on bundle count and whether the app accepts user file uploads.
Technical risk. The dominant risk remains cold start: container compilation takes 1–20s on a fresh Lambda, and fresh Lambdas happen "a handful of times every day" even at steady traffic. Warm-cache-at-deploy mitigates the first request after deploy, but not scale-out events or AWS-initiated recycles mid-day. This is a p99 latency and tail-latency risk that must be modeled explicitly against whatever SLO the product carries.
3.0.3 elevates a second, previously undocumented risk to first-class status: ephemeral storage exhaustion via request uploads. Before this release, a Symfony app on the Bref runtime never deleted the files uploaded with a request; they accumulated in the invocation environment's /tmp until it filled, at which point everything that writes to /tmp fails — not just uploads, but any temp-file consumer (compiled container artefacts, filesystem session handlers, PDF/image libraries, tempnam usage, cache pools that fell back to disk). The blast radius is the whole process, and the failure arrives as a delayed, load-correlated, intermittent outage rather than a clean error. Two important nuances for planning: the fix deletes files at the start of the next request, not at the end of the current one, so (a) a single invocation that accepts more uploaded bytes than /tmp permits can still fail, and (b) a warm container that serves one upload request and then goes idle retains those bytes until the next request or container recycle, which can be many minutes. And the fix requires Bref 3.0.13+, because earlier Bref versions missed uploads on PHP 8.4+ — meaning a bridge upgrade without a Bref upgrade leaves PHP 8.4 apps unprotected while appearing patched. Note also that 3.0.3 is also a partial security improvement: pre-fix, one request's uploads were readable by a subsequent request on the same warm container, which is a cross-request data-bleed hazard in exactly the same family as the keep-alive static-state risk below.
Key questions for the team.
var/cache or /tmp, and can they all be eliminated or pointed at Redis/DynamoDB/S3?BREF_LOOP_MAX tuning and the shared-state hazards of a kept-alive kernel (static properties, in-memory caches persisting across requests)?bref/monolog-bridge 2.x, changes log format and therefore any existing Logs Insights queries and dashboards)?Stack fit. PHP 8.x + Symfony 5.2 through 8.x (the release history maps cleanly: 0.2.0 for Symfony 5.2+, 1.0.0 for Symfony 7, 1.1.1 for Symfony 8, 3.0.x for Bref 3.0). Bref v3 is the current target; Bref v2 is supported on the 0.2.x line only. Composer-installable, MIT, no exotic extensions beyond what Bref's layers already provide. Version alignment is the single most important compatibility constraint, and 3.0.3 sharpens it from a triple to a quad: Symfony / Bref / bridge / PHP. Bridge 3.0.3 requires Bref 3.0.13+, and that floor exists specifically because of a PHP 8.4 divergence — so "we're on PHP 8.3, does it matter?" is a question to answer rather than assume. The 2.0.0/3.0.0 releases carrying identical changelogs is a standing reminder to pin explicitly rather than float.
Migration path. Do it in three increments, not one.
Kernel extends BaseKernel → BrefKernel, deploy with the warm-cache build step, but stay on PHP-FPM. This isolates cache/filesystem breakage from runtime breakage. Ship it, watch error rates and cold-start duration for a week. Worth stating explicitly to stakeholders: PHP-FPM deployments are not affected by 3.0.3 at all, because FPM already deletes uploads at request end. The staged path therefore has a genuine safety property, not just a sequencing preference.handler: App\Service\MyConsumer, layer.php-8x non-FPM). This is the highest-value, lowest-blast-radius win and validates the runtime story. Uploads are usually irrelevant here.BREF_LOOP_MAX has been chosen with evidence. Before this step, the upload path must be audited and the bridge/Bref pair must be at 3.0.3 / 3.0.13 or later — shipping an upload-accepting app onto the function runtime below that floor reproduces a known, delayed, whole-process failure. Many teams rationally stop at step 2.Compatibility and sequencing. Lock the Symfony/Bref/bridge triple in composer.json with caret constraints on all three and let Renovate/Dependabot group them so a Symfony minor bump can't land without the matching bridge release. Given 3.0.3, group patch releases too, or at minimum alert on them: this release is a correctness fix, not a cosmetic one, and it is the kind of change that a "minors and patches are safe to ignore for a quarter" policy would silently skip. Note the 3.0.1 fix for a Symfony 8.1 breaking change and the 3.0.3 Bref floor — this package is on the critical path for framework and runtime upgrades, so it belongs in the upgrade runbook. The Flex auto-registration fix in 3.0.2 will not retroactively apply to existing apps; if you want request-ID logging on an existing install, add Bref\SymfonyBridge\BrefSymfonyBridgeBundle::class => ['all' => true] to config/bundles.php manually, and treat that as a separate, deliberately-scheduled change because it alters log format.
Non-negotiables in the pipeline. cache:warmup/cache:clear --env=prod in the build, --classmap-authoritative --no-scripts --no-dev, .env.local.php generation, and a CI check that fails if the built artifact contains a populated var/cache/pools directory. Add two more in light of 3.0.3: (a) a dependency assertion that fails the build if bridge < 3.0.3 or Bref < 3.0.13 on any non-FPM runtime; (b) an integration test that exercises a file upload against a Lambda-like environment and asserts /tmp does not grow monotonically across successive invocations.
Maintenance. Low code-maintenance burden, non-trivial version-maintenance burden. The package itself changes rarely, but its release notes show it is repeatedly forced to react to Symfony internals (Symfony 8.1 breakage, HttpKernelInterface signature alignment, Flex plugin registration) and, as of 3.0.3, to runtime-level correctness bugs that had no local repro. Expect one to three forced upgrades per year, each gated on a Bref and/or Symfony upgrade — and note that two of the three 3.0.x patches are fixes you want, not optional hygiene. Budget a named owner; this is a "no one owns it until it blocks a framework upgrade or an incident fires" package, which is exactly the failure pattern to avoid.
Support and bus factor. Effectively a single-maintainer project (mnapoli, Bref's author) with 50 stars and 0 tracked dependents. The dependents count is a measurement artifact — end applications don't show up as Composer dependents — but the small contributor base is real. Mitigation: the code surface is small enough to fork and vendor if upstream stalls, and the org's real support relationship is with Bref proper, which is commercially backed (Bref Cloud). 3.0.3 is a modest positive signal — an upstream maintainer finding and fixing a nasty, non-obvious production bug within the same week is what "well-maintained by one person" looks like — but it doesn't change the structural bus factor. Frame this to stakeholders as "we are adopting Bref, and this bridge is the official Symfony adapter," not "we are adopting a 50-star package."
Scaling and failure modes. Four to plan for explicitly. (1) Cold-start latency: bounded by warm cache, but unbounded in frequency — provisioned concurrency or a scheduled warmer is the only real answer, and it has a cost line. (2) Ephemeral-filesystem writes: the highest-severity silent failure class; a filesystem cache pool that "works" in dev returns stale or missing data under Lambda, usually under load, usually intermittently. Enforce with a static analysis / CI grep, not with code-review discipline. (3) /tmp exhaustion via request uploads: now fixed upstream, but only from 3.0.3 / Bref 3.0.13, only for uploads, and only at next-request boundaries — so residual exposure remains for oversized single requests and for idle warm containers holding files. Because the symptom is "everything that writes to /tmp starts failing," it will initially be misdiagnosed; put it in the runbook by name. (4) Keep-alive state leakage: with the function runtime and BREF_LOOP_MAX > 1, any static or container-level mutable state persists across requests. 3.0.3 closes one concrete instance of this class (uploaded files readable by a later request on the same container); the general hazard — static properties, in-memory caches, per-request context held on singletons — remains and deserves an explicit audit before that step ships. Treat the upload finding as evidence that this audit is worth doing thoroughly rather than as a one-off.
Ramp-up. A Symfony developer is productive with this package in under a day — the API is one base class. The real ramp is Lambda literacy: cold starts, concurrency, layer versioning, serverless.yml versus a container-image workflow, CloudWatch Logs Insights query syntax, IAM for whatever replaces the filesystem cache, and — newly non-optional — the semantics of ephemeral /tmp storage (size limits, per-container lifetime, what persists between requests). For a team without prior serverless experience, plan 2–3 weeks of collective ramp before the HTTP-on-function-runtime decision can be made responsibly, and consider running the async-worker increment first specifically because it teaches the operational model at low risk. Any engineer who has debugged a "disk full in /tmp" incident once will design the upload path correctly thereafter; the goal is to get that lesson from a review or a test rather than from production.
Overall recommendation. Adopt, but scope it honestly: as an enabler for Bref adoption, not as an independent platform bet, and with the HTTP-function-runtime migration treated as optional and evidence-gated rather than as the default endpoint. The TPM's job here is to (a) secure the cold-start SLO trade-off from product, (b) fund the filesystem-cache and upload-path audit as real work rather than a code-review footnote, (c) assign a named owner to the Symfony/Bref/bridge upgrade triple (quad, with PHP) before the first deploy, and (d) if any service is already on the Bref runtime, treat the 3.0.3 + Bref 3.0.13 upgrade as a scheduled remediation with a verification step, not a background Renovate PR.
How can I help you explore Laravel packages today?