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

Clusteer Laravel Package

renoki-co/clusteer

Clusteer is a Laravel package for running Laravel Echo Server in a clustered setup, letting you scale WebSocket broadcasting across multiple nodes with shared Redis and a load balancer while simplifying configuration for horizontally scaled real-time apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites (3.3.0): PHP 8.0+ and Laravel 8.x or 9.x. This release adds Laravel 9 support but drops PHP 7.3/7.4 and Laravel 7.x — check your composer.json platform constraints before upgrading.

  1. Install the package:
    composer require renoki-co/clusteer
    
  2. Publish the config and define an "app" entry (the credentials clients and the broadcaster will share):
    php artisan vendor:publish --tag=clusteer.config
    
    In config/clusteer.php set apps[0].id, key, secret, plus optional capacity, enable_client_messages, enable_statistics, and the Redis connection to use for pub/sub.
  3. Wire broadcasting. Add a clusteer connection in config/broadcasting.php (app id/key/secret + options.host, options.port, options.scheme), or point the existing pusher driver at the clusteer host, then set BROADCAST_DRIVER=clusteer and clear cached config.
  4. Configure the browser client — Laravel Echo with the Pusher broadcaster:
    new Echo({
      broadcaster: 'pusher',
      key: import.meta.env.VITE_CLUSTEER_APP_KEY,
      wsHost: import.meta.env.VITE_CLUSTEER_HOST,
      wsPort: 6001,
      forceTLS: false,
      disableStats: true,
      enabledTransports: ['ws', 'wss'],
    });
    
  5. Start the server and smoke-test:
    php artisan clusteer:start --debug
    
    Subscribe to a public channel in the browser, then fire broadcast(new TestEvent()) from php artisan tinker.

Where to look first: config/clusteer.php (all knobs), src/ClusteerServiceProvider.php (driver registration), the Clusteer broadcaster class (HTTP payload shape), the clusteer:start command (host/port/debug options), and routes/channels.php for private/presence authorization.

First real use case: replacing a hosted Pusher/Ably dependency for live notifications, chat, or dashboards when you already run multiple app servers and want the WebSocket tier to scale horizontally over your own Redis.

Implementation Patterns

Multi-node topology. Run one clusteer:start process per app node, all pointed at the same Redis instance/database. The Laravel broadcaster POSTs an event to the configured host (one node), that node publishes to Redis, and every node fans the message out to its own connected sockets. Put the broadcaster's host behind a load balancer, or point each node at its own local process to avoid a single entry point.

Process supervision. Keep the server alive with Supervisor/systemd (autorestart=true, capture stdout/stderr). Treat it like a queue worker: it is long-running and holds old code, so restart it on every deploy.

Channel authorization. Use standard Broadcast::channel() callbacks in routes/channels.php. Private and presence channels hit Laravel's /broadcasting/auth endpoint, so normal guards/session auth apply — including presence member lists.

Client events ("whisper"). Enable enable_client_messages per app in config/clusteer.php if clients should emit directly; leave it off for server-authoritative feeds.

Local vs production. In development, run a single node and toggle BROADCAST_DRIVER=log when you don't need sockets. In production, keep --debug only while diagnosing; it is noisy.

Testing. Assert broadcasts with Event::fake() / Broadcast::fake() in feature tests; the WebSocket server isn't needed for those. Reserve live-server checks for a small integration suite that subscribes and fires a real event.

TLS. Terminate TLS at nginx/HAProxy (proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";) and forward to the clusteer port. Set the broadcaster/Echo scheme/forceTLS to match so generated auth URLs and the client handshake stay consistent.

Gotchas and Tips

  • Upgrade breakage in 3.3.0: no PHP 7.3/7.4, no Laravel 7. If you're stuck on that stack, stay on the previous 3.x line and pin the constraint; on Laravel 9 you must be on 3.3.0+.
  • Credential drift is the #1 failure: app id/key/secret must match across config/clusteer.php, the broadcasting connection, and the Echo client. A mismatch shows up as a 403 on handshake or on /broadcasting/auth.
  • Config caching: php artisan config:cache freezes clusteer config. Re-run it on deploy after changing apps or Redis settings.
  • Redis pub/sub is fire-and-forget. No persistence, replay, or delivery guarantee; a node that's down simply misses messages for its clients (they reconnect). Don't build guaranteed-delivery semantics on it.
  • Cross-node silence usually means the nodes are on different Redis connections/databases or different pub/sub channel prefixes — verify with redis-cli monitor while firing an event.
  • Auth endpoint problems: 419 = CSRF token missing on the Echo auth headers; 403 = channel callback denied or wrong guard; cross-domain cookies require correct session domain and Broadcast::routes(['middleware' => ['web']]).
  • Mixed content: if the page is HTTPS, the socket must be wss (forceTLS: true); otherwise the browser silently blocks the connection.
  • Capacity limits per app can reject connections — check the app entry before blaming the proxy.
  • Stats client noise: set disableStats: true in Echo unless you've enabled statistics for that app.
  • Debugging checklist: redis-cli ping; confirm the process is listening (ss -lntp); run with --debug; inspect the handshake and the /apps/{id}/events POST in the browser/network tab; then confirm the event reached Redis with redis-cli monitor.
  • Extension points: custom Redis connection name, per-app capability flags, and a custom broadcaster binding if you need to alter the HTTP payload or add headers.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings