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

Laravel Sse Laravel Package

sinemacula/laravel-sse

A Laravel package for Server-Sent Events (SSE) that makes it easy to stream real-time updates from your app to browser clients. Simplify live notifications, progress updates, and event broadcasting with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

What it is: sinemacula/laravel-sse adds Server-Sent Events to a Laravel app — a long-lived HTTP response that pushes named events to the browser over a single connection, using the native EventSource API instead of a WebSocket stack.

Install and publish:

composer require sinemacula/laravel-sse
php artisan vendor:publish --tag=laravel-sse-config   # writes config/laravel-sse.php

Confirm the tag name in vendor/sinemacula/laravel-sse/ before assuming — a missing tag is the most common first stumble.

Where to look first, in this order:

  1. config/laravel-sse.php — the stream route path, middleware, and any event/keep-alive settings. This file defines the package's whole surface area; read it before reading docs.
  2. php artisan route:list | grep -i sse — shows the endpoint the package registered and which middleware group it landed in.
  3. The package's own event classes / contracts under vendor/sinemacula/laravel-sse/src — this tells you what you're expected to extend or implement for a custom event.

First use case: a status/progress stream. Register an event, hit the route from a page with new EventSource('/sse'), and console.log the payload. Do that end-to-end before wiring it into a real feature — SSE failures are almost always transport-level (buffering, middleware, proxy) rather than application-level, and you want to discover that on a throwaway route.

Laravel 13 note (v1.1.0): support for Laravel 13 was added in 1.1.0 (PR #28). Minor bump, no documented breaking changes — so existing 1.0 integrations should upgrade cleanly. On Laravel 13 you need ^1.1; check composer.json for the PHP constraint bump that usually accompanies a new Laravel major, since your CI matrix may now fail on an older PHP.

Implementation Patterns

Treat the stream as a first-class route, not a controller action. The package registers its own route; keep it there and control access via config middleware rather than re-implementing a controller. Applying auth/can: middleware in config means authorization is consistent with the rest of the app and doesn't drift.

Event-per-meaning, not event-per-model. Define a small set of named events (progress.updated, job.finished, notification.created) and put a discriminated payload inside. Clients then register a handful of listeners instead of parsing a generic message. This also keeps the front-end stable as the back-end evolves.

Fan-out pattern for progress reporting: dispatch a queued job, have the job write progress to your cache/DB, and let the stream read that state on an interval and emit deltas. Keep the stream a reader of state — never let it own the work. If the connection drops, the client reconnects and re-syncs from the same source of truth.

Pair with EventSource reconnect semantics. Browsers auto-reconnect on drop. Design payloads to be resumable (include an id or sequence number) so a reconnect doesn't replay stale state or duplicate a notification in the UI. Send a terminal event and let the client call .close() rather than holding the connection open forever.

Testing: assert on the response type and body rather than trying to await a live stream. A streamed response can be inspected via $response->streamedContent() (or by capturing the callback) — assert the emitted event names and payload shape. For integration coverage, bind an in-memory sink and assert what the package would have written.

Front-end integration tip: the stream route is same-origin, so cookies flow as normal — no token juggling. If you go cross-origin you'll need CORS plus withCredentials, and that's a different set of problems; stay same-origin unless forced.

Gotchas and Tips

Output buffering is the #1 killer. SSE frames must be flushed as written. If ob_get_level() is non-zero, if compression (zlib.output_compression, mod_deflate) is on, or if a proxy (nginx, Cloudflare) is buffering, events arrive in one lump at the end — which looks exactly like "the package is broken." Verify with curl -N on the endpoint; if curl streams but the browser doesn't, it's buffering, not PHP.

Proxy timeouts. nginx proxy_read_timeout (default 60s) and similar defaults will sever idle streams. Either emit a keep-alive comment at an interval shorter than the shortest timeout in the chain, or configure the timeout. Load balancers are typically worse than the web server — check both.

PHP-FPM worker exhaustion. Each open stream holds a worker. Ten concurrent dashboards on a 10-worker pool and the whole app is down. This is the reason SSE is a poor fit for wide fan-out; for many subscribers, consider whether polling or a dedicated streaming service is cheaper than the extra FPM capacity.

Session locking. Laravel's session middleware locks the session file for the request duration. A long-held stream can serialize every other request from that user. If you see unrelated requests hanging only while a stream is open, exclude the stream route from session middleware in config.

Middleware ordering matters more than usual. Anything that wraps the response body (response caching, ETag, debugbar, gzip) can corrupt or delay frames. Keep the stream route in a slim middleware group and exclude it from anything that mutates output.

Debugging checklist, in order: curl -N → check Content-Type: text/event-stream → check no Content-Length → check X-Accel-Buffering: no if behind nginx → then look at application code. Application bugs are the last suspect, not the first.

Extension point: subclassing/extending the package's event class is the supported way to add custom event names and payloads — prefer that over hand-rolling a raw response()->stream(), otherwise you lose the package's framing and keep-alive behaviour and end up maintaining a fork.

Upgrade check for 1.1.0: pin ^1.1 and run the suite; the Laravel 13 addition is additive, but verify your package-discovery and published config are still in sync (re-publish or diff the config if the minor release touched it) before assuming a silent upgrade.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource