Scaling Laravel Reverb Horizontally in Production | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Laravel Reverb WebSocket Scaling: Channels, Presence, and Horizontal Deployment        On this page       1. [  Why a Single Reverb Node Breaks Under Load ](#why-a-single-reverb-node-breaks-under-load)
2. [  The Redis Pub/Sub Bridge ](#the-redis-pubsub-bridge)
3. [  Presence Channel State Across Nodes ](#presence-channel-state-across-nodes)
4. [  Load Balancer Configuration ](#load-balancer-configuration)
5. [  Supervisor and Process Management ](#supervisor-and-process-management)
6. [  Health Checks and Observability ](#health-checks-and-observability)
7. [  Key Takeaways ](#key-takeaways)

  ![Laravel Reverb WebSocket Scaling: Channels, Presence, and Horizontal Deployment](https://cdn.msaied.com/410/2698f47a7daff990e9807996fe0f493c.png)

  #laravel   #reverb   #websockets   #redis   #broadcasting  

 Laravel Reverb WebSocket Scaling: Channels, Presence, and Horizontal Deployment 
=================================================================================

     11 Jul 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   Why a Single Reverb Node Breaks Under Load  ](#why-a-single-reverb-node-breaks-under-load)
2. [  02   The Redis Pub/Sub Bridge  ](#the-redis-pubsub-bridge)
3. [  03   Presence Channel State Across Nodes  ](#presence-channel-state-across-nodes)
4. [  04   Load Balancer Configuration  ](#load-balancer-configuration)
5. [  05   Supervisor and Process Management  ](#supervisor-and-process-management)
6. [  06   Health Checks and Observability  ](#health-checks-and-observability)
7. [  07   Key Takeaways  ](#key-takeaways)

 Why a Single Reverb Node Breaks Under Load
------------------------------------------

Laravel Reverb is a first-party WebSocket server that integrates tightly with Laravel's broadcasting system. A single node works perfectly in development and handles modest traffic, but the moment you add a second application server — or run Reverb behind a load balancer — you hit a fundamental problem: **WebSocket connections are stateful and sticky to one process**.

Client A connects to node 1. Client B connects to node 2. When your application broadcasts an event, only the node that received the HTTP request knows about it. Without a shared message bus, half your users miss the event.

The Redis Pub/Sub Bridge
------------------------

Reverb ships with a Redis scaling driver that solves this with a publish/subscribe bus. Every Reverb node subscribes to the same Redis channel. When any node receives a broadcast, it publishes to Redis; every other node picks it up and pushes it to its own connected clients.

Enable it in `config/reverb.php`:

```php
'scaling' => [
    'driver' => 'redis',
    'connection' => env('REVERB_SCALING_CONNECTION', 'default'),
],

```

Then make sure your `redis` connection in `config/database.php` points at the same Redis instance (or cluster) that all Reverb nodes share. A dedicated Redis database index keeps Reverb traffic isolated:

```php
'reverb_scaling' => [
    'url' => env('REDIS_URL'),
    'host' => env('REDIS_HOST', '127.0.0.1'),
    'password' => env('REDIS_PASSWORD'),
    'port' => env('REDIS_PORT', '6379'),
    'database' => env('REVERB_REDIS_DB', '1'),
],

```

Reference it: `REVERB_SCALING_CONNECTION=reverb_scaling`.

Presence Channel State Across Nodes
-----------------------------------

Presence channels track *who is online*. In a single-node setup, that state lives in memory. Across nodes, each node only knows about its own connections — so `channel:here` events become inconsistent.

Reverb stores presence membership in Redis when the scaling driver is active. The key pattern is `reverb:presence:{channel}`. You should **never** query this key directly; instead rely on the `here`, `joining`, and `leaving` client events. What you *do* need to ensure is that your Redis instance has enough memory and that you set a sensible TTL policy — presence keys are cleaned up on disconnect, but a crashed node can leave orphaned entries until the key expires.

Force a short key TTL in your Reverb config:

```php
'presence' => [
    'timeout' => 120, // seconds before a stale member is evicted
],

```

Load Balancer Configuration
---------------------------

WebSocket connections require HTTP Upgrade. Most load balancers need explicit configuration:

```nginx
upstream reverb {
    least_conn;
    server reverb1:8080;
    server reverb2:8080;
}

server {
    listen 443 ssl;

    location /app/ {
        proxy_pass http://reverb;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 3600s;
    }
}

```

Note `least_conn` rather than round-robin. WebSocket connections are long-lived, so round-robin will pile connections onto whichever node happened to be first. `least_conn` distributes active connections more evenly.

Supervisor and Process Management
---------------------------------

Each Reverb node should run under Supervisor with restart-on-failure:

```ini
[program:reverb]
command=php /var/www/artisan reverb:start --host=0.0.0.0 --port=8080
autostart=true
autorestart=true
stopwaitsecs=10
stdout_logfile=/var/log/reverb.log

```

Set `stopwaitsecs` high enough for in-flight connections to drain gracefully. Reverb sends a close frame to clients on SIGTERM; clients with reconnect logic will re-connect to another node transparently.

Health Checks and Observability
-------------------------------

Reverb exposes a `/apps/{appId}/channels` REST endpoint (authenticated with your app secret) that returns active channel counts. Wire this into your uptime monitor or Prometheus scraper to alert on node divergence — if two nodes report wildly different channel counts, your Redis pub/sub bridge may have silently failed.

Key Takeaways
-------------

- Enable the Redis scaling driver so all Reverb nodes share a pub/sub bus.
- Use a dedicated Redis database index to isolate Reverb traffic.
- Presence channel state is stored in Redis automatically; set a `presence.timeout` to evict stale members from crashed nodes.
- Configure your load balancer with `Upgrade` headers and `least_conn` balancing.
- Run each node under Supervisor with graceful shutdown via `stopwaitsecs`.
- Monitor channel counts per node via the Reverb REST API to catch pub/sub failures early.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-reverb-websocket-scaling-channels-presence-and-horizontal-deployment&text=Laravel+Reverb+WebSocket+Scaling%3A+Channels%2C+Presence%2C+and+Horizontal+Deployment) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-reverb-websocket-scaling-channels-presence-and-horizontal-deployment) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Do I need a Redis cluster, or will a single Redis instance work for Reverb scaling?        A single Redis instance is sufficient for most deployments. Redis pub/sub is extremely fast and the message volume from WebSocket broadcasts is typically low. Only move to a Redis cluster if your Redis instance itself becomes a bottleneck, which is rare before thousands of concurrent connections. 

      Q02  What happens to connected clients when a Reverb node restarts?        Reverb sends a WebSocket close frame on SIGTERM. Laravel Echo and Pusher-compatible clients have built-in reconnect logic, so clients will automatically reconnect to another available node within a few seconds. The presence channel will emit a `leaving` event for the disconnected client and a `joining` event when they reconnect. 

      Q03  Can I run Reverb behind AWS ALB or Cloudflare?        Yes. AWS ALB supports WebSocket upgrades natively — enable sticky sessions only if you cannot use the Redis scaling driver. Cloudflare proxies WebSockets on paid plans; ensure your Cloudflare timeout settings exceed your expected connection duration, as the default 100-second idle timeout will drop long-lived connections. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Filament v3 Table Bulk Actions: Custom Confirmation, Progress Feedback, and Job Dispatch](https://cdn.msaied.com/412/68d290c667a619900211863678fa0b1f.png) filament laravel queues 

### Filament v3 Table Bulk Actions: Custom Confirmation, Progress Feedback, and Job Dispatch

Go beyond the default delete bulk action. Learn how to build Filament v3 bulk actions with custom confirmation...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 11 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/filament-v3-table-bulk-actions-custom-confirmation-progress-feedback-and-job-dispatch) [ ![Practical RAG in Laravel: pgvector, Embeddings, and Retrieval Pipelines](https://cdn.msaied.com/411/8d5b164ce43b1c6b9b658b7f72a0c369.png) laravel ai pgvector 

### Practical RAG in Laravel: pgvector, Embeddings, and Retrieval Pipelines

Build a production-ready retrieval-augmented generation pipeline in Laravel using pgvector, OpenAI embeddings,...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 11 Jul 2026     4 min read  

  Read    

 ](https://msaied.com/articles/practical-rag-in-laravel-pgvector-embeddings-and-retrieval-pipelines-1) [ ![Laravel Enum Casts, Backed Enums, and Value Semantics in PHP 8.3](https://cdn.msaied.com/408/3534df365ffb2c8f6c430180bfaba8f1.png) laravel php8.3 enums 

### Laravel Enum Casts, Backed Enums, and Value Semantics in PHP 8.3

PHP 8.3 backed enums combined with Laravel's native enum casting unlock type-safe domain models. Learn how to...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 10 Jul 2026     1 min read  

  Read    

 ](https://msaied.com/articles/laravel-enum-casts-backed-enums-and-value-semantics-in-php-83) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
