Skip to content
AXVI BUILD · WRITE · SHIP
Projects

WSBro

Pusher-compatible WebSocket server for Laravel in one small Go binary. A drop-in replacement for Reverb and Pusher.

WSBro

Real-time for Laravel without Pusher bills or a PHP process to babysit. WSBro is one 20 MB binary that speaks the Pusher protocol: point Laravel at it and broadcasting just works.

Why WSBro

  • Drop-in for Reverb and Pusher. Laravel's own reverb and pusher broadcasters, Laravel Echo and every Pusher SDK work unchanged. No package to install, no code to change.
  • One binary, nothing else. No PHP worker, no Node.js, no database. docker run and you are live.
  • Fast and frugal. 100,000 concurrent connections in 3.3 GB of RAM; 160,000 messages per second with a p99 latency of 3 ms on one instance.
  • A dashboard you will actually use. Live debug console, presence members, test events, connections you can disconnect. Built in, works offline.
  • Proven, not promised. Every change runs a real Laravel 12 and 13 app with laravel-echo and pusher-js through WSBro, on both broadcasters.

Quick start

docker run -d --name wsbro -p 6001:6001 \
  -e WSBRO_APP_ID=my-app \
  -e WSBRO_APP_KEY=my-key \
  -e WSBRO_APP_SECRET=my-secret \
  -e WSBRO_DASHBOARD_PASSWORD=change-me \
  ghcr.io/axvilab/wsbro

Without Docker, download a binary from the releases page or run go install github.com/axvilab/wsbro@latest. The dashboard is at http://localhost:6001/dashboard.

Use it with Laravel

Already on Reverb? Keep your code and your .env, stop running php artisan reverb:start and point REVERB_HOST and REVERB_PORT at WSBro:

BROADCAST_CONNECTION=reverb

REVERB_APP_ID=my-app
REVERB_APP_KEY=my-key
REVERB_APP_SECRET=my-secret
REVERB_HOST=127.0.0.1
REVERB_PORT=6001
REVERB_SCHEME=http

Everything works as it does with Reverb or Pusher:

broadcast(new OrderShipped($order))->toOthers();
Echo.private(`App.Models.User.${userId}`).listen('.order.shipped', (e) => { /* ... */ });

Echo.join('chat')
    .here((users) => {})
    .joining((user) => {})
    .leaving((user) => {})
    .listenForWhisper('typing', (e) => {});

Features

  • Pusher protocol 7: public, private, presence, encrypted and cache channels; client events (whisper); user authentication, sendToUser and terminating connections.
  • Pusher HTTP API: trigger, batch, channel info and presence users, signed exactly like Pusher, with a replay-safe body_md5 check.
  • Webhooks: channel_occupied, channel_vacated, member_added and member_removed in the Pusher format, verifiable with the official SDKs.
  • Multi-app: many apps on one server, fully isolated, each with its own limits, allowed origins and webhook.
  • Protection: connection, message rate, channel and payload limits; allowed origins; slow and dead clients are dropped without affecting others.
  • Scaling: Redis or NATS to run several instances; a graceful shutdown hands clients over.
  • Observability: JSON and Prometheus metrics, JSON logs and a health endpoint.
  • Operations: TLS, a 20 MB multi-arch image running as non-root, a systemd-friendly binary and strict configuration validation.

Dashboard

The dashboard is built in and enabled with WSBRO_DASHBOARD_PASSWORD. It shows every app, channel and connection, and lets you send test events.

WSBro dashboard: apps, channels and connections at a glance

The debug console shows every connection, subscription and event live:

WSBro debug console with live connections, subscriptions and events

How it compares

Feature WSBro Laravel Reverb Soketi Sockudo
Runs as single Go binary PHP process Node.js single Rust binary
Pusher protocol yes yes yes yes
Laravel's reverb broadcaster yes yes yes yes
Dashboard built in, with a live debug console Laravel Pulse cards none separate service
Scaling Redis, NATS Redis Redis, NATS, cluster many brokers
Focus small, simple, Laravel-first Laravel's official solution general purpose feature-rich platform

All of them are good projects. WSBro is for teams that want Reverb's compatibility without running PHP for WebSockets, and the smallest possible thing to deploy and understand.

Roadmap

  • Shared presence state across instances: exact here() lists and channel counts with Redis.
  • A ready-made Helm chart.
  • Webhook retries with back-off.
  • Subscription count events (pusher:subscription_count).
Esc