Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Event Source Laravel Package

garlic/event-source

garlic/event-source is a Laravel/PHP event sourcing package for persisting domain changes as immutable events, rebuilding aggregates, and projecting read models. It helps teams add auditability and decoupled workflows to their applications.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package name (event-source-bundle) and the garlicservices org point to a Symfony bundle, not a Laravel package. Laravel does not consume Symfony bundles — it consumes service providers, facades, and config-publishable packages. There is no evidence of a composer.json extra.laravel.providers entry, a GarlicEventSourceServiceProvider, or a config stub. Assuming the underlying SSE logic isn't cleanly separated from the DI container wiring (typical for bundles of that era), a Laravel team would be integrating the framework glue rather than the protocol implementation. Since SSE on top of Symfony HttpFoundation is roughly a StreamedResponse with correct headers, the deliverable here is thin: the package is unlikely to encode much more than header conventions, a heartbeat loop, and an event formatter — all of which a mid-level engineer can reproduce in well under a day.

Integration feasibility. Low, and falling. The 2017-09-07 release predates Laravel 5.6 and lands in the Symfony 2.8/3.x era. Modern Laravel (10/11/12) pins symfony/* to 6.x/7.x, so Composer resolution will almost certainly fail on transitive constraints before any code is loaded. There is no Laravel package discovery, no documented config surface, and — with 0 stars and 0 dependents — no issue history to consult when it breaks. Treat "integration" as "vendoring source into app/Support/Sse/ and taking ownership of it."

Technical risk. High across every axis:

Risk Assessment
Abandonment 8+ years without a release; no security disclosure channel
Ecosystem drift Symfony 2/3 constraints vs. Laravel's Symfony 6/7 pinning
PHP compatibility Written for PHP 5.6/7.0; unverified on 8.1–8.4 (deprecations, each(), dynamic properties, untyped internals)
Validation Zero dependents means zero production signal; no confidence in edge-case behavior
License/lineage Must confirm a permissive license and that the code is original before vendoring

The only genuinely low-risk part is the domain: SSE is a small, stable, well-specified protocol (text/event-stream framing, id:, event:, retry:, Last-Event-ID replay). That reduces the value of a dependency and raises the cost of a stale one.

Key questions for the technical spike (1–2 days, timeboxed):

  1. Does the package contain a reusable, container-free SSE writer class, or is the logic entangled with Symfony DI/event dispatcher?
  2. What are the exact composer.json PHP and symfony/* constraints, and does the code run under PHP 8.3 without deprecation notices?
  3. Does it implement heartbeat/keep-alive, retry: hints, and Last-Event-ID resume — or only naive write-and-flush?
  4. Who is the upstream maintainer, is there a fork we can track, and what license applies?
  5. What is the actual source of events in our system (Redis pub/sub, DB cursor, queue) and does the package prescribe one?

If Q1 yields a clean, container-free class under a permissive license, a vendored copy is defensible. Otherwise the answer is no-go.

Integration Approach

Stack fit — recommended alternative. Do not adopt the bundle. Implement SSE natively, which in Laravel is a response()->stream() closure (or StreamedResponse directly) emitting text/event-stream with Cache-Control: no-cache, X-Accel-Buffering: no, and a periodic heartbeat comment (:ping\n\n) every 15–25s. Pair it with a fan-out source: Redis pub/sub for multi-node deployments, or a DB cursor poll for simple cases. If we want a maintained, purpose-built component, Mercure (standalone hub, Symfony-adjacent but framework-agnostic) or a managed service (Ably/Pusher) is the realistic comparison — not this package.

Migration path. There is no installed base to migrate from. If a prototype already vendors the bundle, the path is: extract the route/controller boundaries, reimplement the writer behind the same route contract, delete the vendored tree, and keep the client-side EventSource code untouched — the browser API is identical, which makes the swap low-drama once endpoints are stable.

Compatibility checklist before any code is written. Confirm PHP 8.2+ support, Laravel 10/11 target, absence of symfony/* conflicts, PSR-4 autoloading that we control, and a composer.json we can safely pin in CI. For any vendored code, add it to our dependency-review and static-analysis (PHPStan/Larastan) surface so it isn't a blind spot.

Sequencing.

  1. Spike (1–2 days): run the five key questions; produce a go/no-go memo. Default posture: no-go.
  2. Reference implementation (3–5 days): SseController + SseStream writer + Redis pub/sub bridge + heartbeats; unit-test the framing (event id, multi-line data, retry:).
  3. Infrastructure hardening (parallel): Nginx proxy_buffering off; gzip off; ALB/NLB idle timeout raised above heartbeat interval; response buffering disabled at every hop.
  4. Capacity model + load test before enabling for more than an internal cohort.
  5. Client reconnect semantics (Last-Event-ID, exponential backoff) validated end-to-end.

Operational Impact

Maintenance. Ownership transfers entirely to us either way — the question is whether we own a small in-house module or a vendored 2017 bundle we did not write. The former is a maintenance task; the latter is archaeology. On-call engineers debugging an SSE disconnect at 02:00 will be reading our own code in one scenario and unfamiliar, abandoned Symfony DI code in the other.

Support. None available. Zero dependents means no Stack Overflow corpus, no CVE feed, no upgrade path. This is the decisive operational fact: we would be the sole maintainer of a package we have no relationship with.

Scaling. This is the real operational cost of SSE on PHP-FPM and it exists regardless of package choice — the package does not solve it. Each open connection occupies a PHP-FPM worker for its full lifetime. With a pool of 50 children, node #1 tops out near 50 concurrent streams before the entire application stalls, not just SSE. Mitigations, in order of preference: dedicated SSE worker pool / separate service so streams cannot starve request traffic; Laravel Octane (Swoole/RoadRunner) for coroutine-based concurrency; Redis pub/sub fan-out so N app nodes don't each need a DB cursor; and hard server-side max_execution_time guards with graceful close-and-reconnect. Budget for the capacity model explicitly — SSE is a connection-count problem, and connection count is where the cost lands.

Failure modes to design against.

  • Silent buffering at Nginx/ALB/Cloudflare collapses streaming into a single delayed response — symptoms look like "events arrive in a burst every 60s." Enforce X-Accel-Buffering: no and disable compression.
  • Worker exhaustion under connection spikes; without a separate pool this is a full-site outage, not a degraded feature.
  • Proxy idle timeouts (commonly 60s) sever quiet streams; heartbeats must be shorter than the tightest timeout in the path.
  • Memory growth in long-lived PHP loops (accumulated buffers, unbounded log context); enforce per-connection iteration caps.
  • Lost events on reconnect if Last-Event-ID replay isn't implemented — clients silently miss messages and this surfaces as data-correctness bugs, not infra alerts.
  • Zombie connections from clients that vanish without FIN; require heartbeat-write failure detection to reclaim workers.

Ramp-up. Low for the in-house path — response()->stream() is a familiar Laravel idiom and the SSE spec is small; one engineer, one sprint including tests. The bundle path has negative ramp-up efficiency: time is spent reverse-engineering 2017 Symfony conventions and patching PHP 8 incompatibilities before the first byte is streamed, with no guarantee of reaching production.

Recommendation. Reject adoption; build the ~100–200 line SSE module in-house, or evaluate Mercure as a maintained alternative. The bundle's only conceivable role is as a reference read for header handling and heartbeat patterns during the spike — treat it as documentation, not a dependency.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core