webalternatif/flysystem-failover-bundle
Symfony bundle that adds a failover adapter to Flysystem, automatically switching to a backup storage backend when the primary one fails. Configure multiple adapters with priorities so reads and writes keep working during outages or misconfigurations.
Package: webalternatif/flysystem-failover-bundle — v0.8.0 (Oct 3, 2026)
Evidence base: The release provides only a changelog link; no diff, no migration notes, no semver signal beyond the version bump. Assessment below is scoped accordingly and should be treated as provisional until the changelog and tag diff are reviewed.
Architecture fit. This is a Symfony bundle, not a Laravel package. That distinction matters more than usual here: bundles ship a Bundle class, a DI Extension, and YAML service wiring, none of which Laravel consumes. The reusable asset is the underlying Flysystem failover adapter logic, not the bundle surface. Our fit is therefore "library-level reuse, framework-level bypass" — we would depend on the package for its adapter and re-register it through Laravel's filesystem driver layer. Any assessment that assumes composer require + auto-discovery is wrong and should be corrected at the outset.
Conceptually, the capability is well-aligned with a real gap: Laravel's Storage disk abstraction has no first-class failover or redundancy semantics. A write-through/fallback adapter is a plausible building block for multi-region or primary+secondary object storage patterns. The architectural question is whether we want failover (transparent substitution, invisible to the caller) or replication/verification (explicit, observable, reconcilable). These are different products; failover is the cheaper one to build and the more expensive one to operate.
Integration feasibility. Moderate. Two viable paths: (a) Storage::extend() to register a custom driver that composes the failover adapter, keeping the Laravel ergonomics (Storage::disk('redundant')->put(...)); or (b) use the Flysystem adapter directly at the League level and bypass Storage for the affected code paths. Path (a) is preferable for developer experience but requires us to own an adapter shim that has no upstream maintainer — a permanent maintenance tax. Path (b) fragments our storage access patterns.
Blocking unknowns: whether the adapter targets Flysystem v3 (Laravel 10/11/12 ship v3) or still supports v1/v2; whether it pulls in symfony/http-kernel or other framework packages as hard dependencies, which would be a non-starter for a Laravel-only service.
Technical risk. Several, in descending order of severity:
Key questions for the maintainer (or the changelog review):
write, read, delete, copy, move, listContents, url/temporary URLs?Stack fit. Laravel's filesystem layer is a thin facade over Flysystem v3 with a driver registry. That is a favorable seam: we can register the failover adapter as a custom driver without forking anything, and without adopting Symfony bundle machinery. Recommended shape:
acme/laravel-filesystem-failover) that depends on webalternatif/flysystem-failover-bundle, exposes a failover driver via Storage::extend(), and centralizes configuration in config/filesystems.php.^0.8) and treat every bump as a reviewed change, not an automatic update.Migration path. Do not migrate existing disks. Introduce the driver as a new disk alongside current ones, and route a single, low-criticality workload through it first.
Suggested sequencing:
Storage::extend() wrapper with mandatory structured logging on every failover event and a counter metric. Non-negotiable: a failover that produces no telemetry is not shippable.Compatibility. Confirm the package resolves against our PHP version and Laravel major. Test against the lowest Laravel version we support, not just the newest — the driver registry API has been stable for a while but Storage::extend() call-site conventions have shifted.
Sequencing note. Steps 2 and 3 can partially overlap, but step 3 must complete before step 4. Deploying failover without having characterized its semantics is the specific failure mode this plan exists to prevent.
Maintenance. We inherit two ongoing costs: (a) tracking a 0.x upstream that we cannot auto-upgrade, and (b) owning the Laravel shim, which has no upstream. Estimated steady-state: a few hours per quarter for version review, plus the shim's share of general platform maintenance. Acceptable given the shim is small; unacceptable if it grows, so keep it strictly to driver registration and configuration mapping.
Support. No commercial support, single-maintainer project, Symfony-oriented community. Internal expertise must be built deliberately — plan for one primary and one secondary engineer, with the failover runbook written by the pilot team while context is fresh. Expect Laravel-specific questions to go unanswered upstream; our shim is the support boundary.
Scaling. The adapter is I/O-bound and stateless, so horizontal scaling is not a concern. Two real costs: throughput — a failing primary adds timeout latency to every request until the failure is detected, so failover must be paired with a circuit breaker, or tail latency will spike service-wide; and storage — redundancy roughly doubles object storage and egress. For large buckets, quantify this before committing, since egress on cross-region replication is often the line item that kills the business case.
Failure modes to instrument and alert on:
| Mode | Symptom | Detection |
|---|---|---|
| Silent sustained failover | All traffic on secondary | Failover event rate sustained > baseline |
| Divergence | Primary missing objects written during outage | Periodic object-count/checksum reconciliation |
| Stale reads | Reads fail over to aged secondary copy | Read-source tagging in logs |
| Partial delete | Orphaned objects, billing creep | Storage-growth anomaly vs. request-volume |
| Timeout amplification | p99 latency spike during primary degradation | Per-disk latency histograms |
| Dual failure | Both targets unreachable | Standard availability alerting |
Ramp-up. Realistic estimate: 1–1.5 engineer-weeks to reach confident pilot deployment, including audit and characterization; 3–4 weeks elapsed to a decision on wider rollout. The learning curve is not the adapter itself (small, readable) but the operational model — specifically, teaching the team that "the write succeeded" no longer implies "the write landed where you think it did." That conceptual shift is the real ramp-up cost and should drive onboarding material.
Recommendation. Worth a time-boxed pilot, not a broad adoption. The capability gap is real, the integration seam is clean, and the pilot cost is low. But the decision to widen scope should be gated on two findings from the pilot: (1) upstream provides, or we can cheaply build, reconciliation for post-failover divergence, and (2) failover is fully observable. If either fails, the correct outcome is to keep the pilot's instrumentation and build the redundancy explicitly rather than depend on a 0.x package at the persistence layer.
How can I help you explore Laravel packages today?