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

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

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

  [ home ](https://www.msaied.com)    [ articles ](https://www.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%2Fwww.msaied.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%2Fwww.msaied.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://www.msaied.com/articles) 

 [ ![DDD Value Objects and DTOs in Laravel Without the Bloat](https://cdn.msaied.com/450/41688537085b86f102fd8c219a35319f.png) laravel ddd php 

### DDD Value Objects and DTOs in Laravel Without the Bloat

Learn how to implement domain-driven value objects and data transfer objects in Laravel using PHP 8.3 readonly...

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

 21 Jul 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/ddd-value-objects-and-dtos-in-laravel-without-the-bloat) [ ![Laravel + Python FastAPI: Image OCR Demo](https://cdn.msaied.com/447/5f3d87146fbf19957973cbc88c6c0155.png) Laravel Python FastAPI 

### Laravel + Python FastAPI: Image OCR Demo

Learn how to call a Python image OCR script from Laravel using FastAPI as the bridge. This premium tutorial wa...

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

 20 Jul 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-python-fastapi-image-ocr-demo) [ ![Scaffold Laravel Packages with the `laravel package` Command in Installer v5.31.0](https://cdn.msaied.com/449/522e744d3c7bae1f214c179a83ae5b88.png) Laravel Installer Package Development CLI 

### Scaffold Laravel Packages with the `laravel package` Command in Installer v5.31.0

Laravel Installer v5.31.0 introduces a `laravel package` command to scaffold packages from the CLI, automated...

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

 20 Jul 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/scaffold-laravel-packages-with-the-laravel-package-command-in-installer-v5310) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.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://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.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)
