Scaling Laravel Reverb WebSockets 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 in Production: Scaling WebSockets Beyond a Single Server        On this page       1. [  Why Reverb Needs Special Attention in Production ](#why-reverb-needs-special-attention-in-production)
2. [  The Core Problem: In-Memory Channel State ](#the-core-problem-in-memory-channel-state)
3. [  Solution: Redis as the Pub/Sub Backbone ](#solution-redis-as-the-pubsub-backbone)
4. [  Nginx: Sticky Sessions Are Non-Negotiable ](#nginx-sticky-sessions-are-non-negotiable)
5. [  Supervisor: Keeping Reverb Alive ](#supervisor-keeping-reverb-alive)
6. [  Health Checks and Graceful Deploys ](#health-checks-and-graceful-deploys)
7. [  Takeaways ](#takeaways)

  ![Laravel Reverb in Production: Scaling WebSockets Beyond a Single Server](https://cdn.msaied.com/180/b3f362d3b1f7da03af9a87a26ffcbdf6.png)

  #laravel   #reverb   #websockets   #redis   #broadcasting  

 Laravel Reverb in Production: Scaling WebSockets Beyond a Single Server 
=========================================================================

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

       Table of contents

1. [  01   Why Reverb Needs Special Attention in Production  ](#why-reverb-needs-special-attention-in-production)
2. [  02   The Core Problem: In-Memory Channel State  ](#the-core-problem-in-memory-channel-state)
3. [  03   Solution: Redis as the Pub/Sub Backbone  ](#solution-redis-as-the-pubsub-backbone)
4. [  04   Nginx: Sticky Sessions Are Non-Negotiable  ](#nginx-sticky-sessions-are-non-negotiable)
5. [  05   Supervisor: Keeping Reverb Alive  ](#supervisor-keeping-reverb-alive)
6. [  06   Health Checks and Graceful Deploys  ](#health-checks-and-graceful-deploys)
7. [  07   Takeaways  ](#takeaways)

 Why Reverb Needs Special Attention in Production
------------------------------------------------

Laravel Reverb is a native PHP WebSocket server built on ReactPHP's event loop. It handles long-lived TCP connections, which means the usual stateless assumptions you make about HTTP workers no longer apply. A single Reverb process holds connection state in memory. The moment you add a second node, clients on node A can't receive events published by a job running on node B — unless you wire up a shared pub/sub backend.

This article covers the exact configuration needed to run Reverb reliably across multiple nodes.

---

The Core Problem: In-Memory Channel State
-----------------------------------------

By default, Reverb tracks which WebSocket connections are subscribed to which channels entirely in the current process's memory. When a queued job calls:

```php
broadcast(new OrderShipped($order));

```

Laravel publishes the event to the configured broadcasting driver. If that driver is `reverb`, the event hits **one** Reverb node via HTTP. Any client connected to a **different** node never sees it.

---

Solution: Redis as the Pub/Sub Backbone
---------------------------------------

Reverb ships with a Redis scaling driver. Enable it in `config/reverb.php`:

```php
'servers' => [
    'reverb' => [
        'driver' => 'reverb',
        'key'    => env('REVERB_APP_KEY'),
        // ...
        'scaling' => [
            'enabled' => true,
            'driver'  => 'redis',
            'connection' => 'default', // your redis connection name
        ],
    ],
],

```

With this enabled, every Reverb node subscribes to a shared Redis channel. When node A receives a broadcast, it publishes to Redis; node B picks it up and fans the message out to its own connected clients.

> **Important:** Use a dedicated Redis connection for Reverb scaling — not the same one your cache or queue uses. Connection contention under load will cause missed messages.

---

Nginx: Sticky Sessions Are Non-Negotiable
-----------------------------------------

WebSocket upgrades require the same TCP connection to persist for the lifetime of the session. You must configure your load balancer to route a given client to the same upstream for the duration of the connection.

With Nginx and `ip_hash`:

```nginx
upstream reverb_nodes {
    ip_hash;
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}

server {
    listen 443 ssl;
    server_name ws.example.com;

    location / {
        proxy_pass http://reverb_nodes;
        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;
    }
}

```

`ip_hash` is a blunt instrument — prefer cookie-based stickiness (`sticky` module) or an AWS ALB with stickiness enabled if you need finer control.

---

Supervisor: Keeping Reverb Alive
--------------------------------

Reverb is a long-running process. Supervisor is the simplest way to manage it:

```ini
[program:reverb]
command=php /var/www/artisan reverb:start --host=0.0.0.0 --port=8080
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
stdout_logfile=/var/log/reverb.log
stderr_logfile=/var/log/reverb-error.log

```

Set `autorestart=true` and monitor the log for `ReactPHP` loop exceptions — an unhandled exception in a coroutine can silently kill the loop without crashing the process.

---

Health Checks and Graceful Deploys
----------------------------------

Reverb exposes no built-in HTTP health endpoint, but you can add a lightweight TCP check. For zero-downtime deploys:

1. Start new Reverb processes on the new release.
2. Drain old connections by removing old nodes from the upstream pool.
3. Wait for `proxy_read_timeout` to expire naturally, or send `SIGTERM` and let existing connections close.

Avoid `SIGKILL` — it drops all open WebSocket connections immediately.

---

Takeaways
---------

- Enable Reverb's Redis scaling driver on any multi-node deployment; in-memory state does not survive across processes.
- Use a dedicated Redis connection for Reverb to avoid contention with cache and queue workloads.
- Configure sticky sessions at the load balancer — WebSocket upgrades require connection affinity.
- Run Reverb under Supervisor with `autorestart=true` and monitor for silent event-loop failures.
- Plan graceful draining during deploys; `SIGKILL` drops all live connections instantly.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-reverb-in-production-scaling-websockets-beyond-a-single-server&text=Laravel+Reverb+in+Production%3A+Scaling+WebSockets+Beyond+a+Single+Server) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-reverb-in-production-scaling-websockets-beyond-a-single-server) 

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

  3 questions  

     Q01  Do I need Redis if I only run a single Reverb node?        No. With a single node, all connection state lives in one process and broadcasts reach every connected client. Redis scaling is only required when you run two or more Reverb processes, whether on the same machine or different servers. 

      Q02  Can I run Reverb under Laravel Octane for better performance?        Reverb already runs its own ReactPHP event loop and is not designed to run inside an Octane worker. They are separate long-running processes. Run Reverb with its own Supervisor program alongside your Octane workers. 

      Q03  How do I monitor the number of active WebSocket connections per node?        Reverb does not expose Prometheus metrics out of the box. You can query the Reverb HTTP API (enabled in config) for connection counts, or push custom metrics from within a scheduled command that calls the Reverb manager to count active channels. 

  Continue reading

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

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

 [ ![Filament at Scale: Multi-Panel Auth, Custom Panels, and Table Query Tuning](https://cdn.msaied.com/183/62be0d95101cf6a9babfd701562186ed.png) filament laravel multi-tenant 

### Filament at Scale: Multi-Panel Auth, Custom Panels, and Table Query Tuning

Running Filament across multiple panels with separate auth guards, scoped queries, and optimised table perform...

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

 15 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/filament-at-scale-multi-panel-auth-custom-panels-and-table-query-tuning) [ ![Partial Indexes and Covering Indexes in PostgreSQL: A Laravel Developer's Guide](https://cdn.msaied.com/182/b7324e1d3db8ad8b9fd3c5d57e2e515a.png) laravel postgresql performance 

### Partial Indexes and Covering Indexes in PostgreSQL: A Laravel Developer's Guide

Partial and covering indexes can eliminate full-table scans and index-only scans in your Laravel apps. Learn w...

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

 15 Jun 2026     4 min read  

  Read    

 ](https://msaied.com/articles/partial-indexes-and-covering-indexes-in-postgresql-a-laravel-developers-guide) [ ![Laravel Gates, Policies, and Response-Based Access Control in Depth](https://cdn.msaied.com/181/5bda736cd48ab747366fdac25d0d0d78.png) laravel authorization security 

### Laravel Gates, Policies, and Response-Based Access Control in Depth

Move beyond simple boolean gates. Learn how Laravel's Response objects, before hooks, policy filters, and inli...

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

 15 Jun 2026     4 min read  

  Read    

 ](https://msaied.com/articles/laravel-gates-policies-and-response-based-access-control-in-depth) 

   [  ![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)
