Hindi
WorkExperienceAboutBlogGitHubContactContact
Back to Blog
LaravelWebSocketReverbReal-Time

Laravel Reverb vs Pusher vs Soketi: Choosing the Right WebSocket

RD

Raman Daksh

June 28, 2025 · 7 min read

Laravel Reverb landed as a first-party WebSocket server in Laravel 11, and it changed the real-time game for the Laravel ecosystem. But should you use it over Pusher, Soketi, or raw WebSockets? I tested all four in production scenarios. Here's what I found.

The Contenders

| Solution | Type | Cost | Setup Complexity | Scalability |

| **Laravel Reverb** | First-party, self-hosted | Free (server cost only) | Low | High (horizontal scaling) |

| **Pusher** | Managed SaaS | Paid (free tier limited) | Minimal | Very High |

| **Soketi** | Open-source, self-hosted | Free (server cost only) | Medium | High |

| **Native WebSockets (Ratchet/ReactPHP)** | Library | Free | High | Moderate |

Laravel Reverb — The New Default

Reverb is Laravel's official WebSocket server, built on top of ReactPHP and PHP 8.2+. It's designed specifically for Laravel Broadcasting:

composer require laravel/reverb
php artisan reverb:install
php artisan reverb:start

That's it. Three commands and you have a production-ready WebSocket server. The configuration lives in your Laravel app:

// config/reverb.php
'app' => [
    'apps' => [
        [
            'app_id' => env('REVERB_APP_ID'),
            'key' => env('REVERB_APP_KEY'),
            'secret' => env('REVERB_APP_SECRET'),
        ],
    ],
],

'scaling' => [
    'enabled' => env('REVERB_SCALING_ENABLED', false),
    'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'),
    'server' => [
        'url' => env('REDIS_URL'),
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'port' => env('REDIS_PORT', 6379),
    ],
],

Benchmarks

I ran Reverb on a $20/month VPS (2 vCPU, 4GB RAM) simulating 10,000 concurrent connections:

  • **Peak throughput**: 28,000 messages/second
  • **Memory per connection**: ~45KB
  • **Latency p99**: 12ms
  • **CPU at 10k connections**: 62%
  • For a self-hosted solution running on PHP, these numbers are impressive. The secret is ReactPHP's event loop — it handles I/O asynchronously without spawning a process per connection.

    Pusher — The Set-and-Forget Option

    Pusher is the incumbent. It's managed, so you don't think about servers, scaling, or uptime:

    // config/broadcasting.php
    'connections' => [
        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'useTLS' => true,
            ],
        ],
    ],

    The Cost Reality

    Pusher's free tier gives you 200,000 messages/day and 100 concurrent connections. For a production app handling 500,000 messages/day with 5,000 concurrent connections, you're looking at **$199/month** on their Scale plan.

    For comparison, running Reverb on a $20/month VPS handles that same load without breaking a sweat. Over a year, that's **$2,148 saved**.

    When Pusher Still Wins

  • You don't want to manage infrastructure
  • Your team lacks DevOps experience
  • You need global edge distribution
  • You're prototyping and want zero setup
  • Soketi — The Open-Source Middle Ground

    Soketi is a Pusher-compatible WebSocket server written in Node.js. It speaks the Pusher protocol, so you swap the URL and keep your client code:

    # Deploy with Docker
    docker run -p 6001:6001 -e SOKETI_DEFAULT_APP_ID=app-id \
      -e SOKETI_DEFAULT_APP_KEY=app-key \
      -e SOKETI_DEFAULT_APP_SECRET=app-secret \
      quay.io/soketi/soketi:latest

    Your Laravel config stays identical to Pusher — just change the host:

    'options' => [
        'host' => env('SOKETI_HOST', '127.0.0.1'),
        'port' => env('SOKETI_PORT', 6001),
        'useTLS' => false,
    ],

    Soketi vs Reverb

    Soketi edges ahead in raw throughput (Node.js event loop is faster than ReactPHP), but Reverb wins in operational simplicity because:

  • **Same language** — PHP devs don't need Node.js knowledge
  • **Tighter Laravel integration** — no protocol translation layer
  • **Native scaling** — Reverb's Redis-based horizontal scaling works out of the box
  • **First-party support** — Laravel core team maintains it
  • Native WebSockets (Ratchet)

    You can build a WebSocket server from scratch with Ratchet or ReactPHP:

    use RatchetServerIoServer;
    use RatchetHttpHttpServer;
    use RatchetWebSocketWsServer;
    
    $server = IoServer::factory(
        new HttpServer(
            new WsServer(
                new YourMessageHandler()
            )
        ),
        8080
    );
    
    $server->run();

    This gives maximum flexibility but requires you to implement broadcasting, presence channels, authentication, and reconnection logic yourself. In practice, the engineering cost rarely justifies it unless you have very specific requirements.

    My Recommendation

    | Use Case | Best Choice |

    | New Laravel project, self-hosted | **Laravel Reverb** |

    | Managed, no ops overhead | **Pusher** (budget permitting) |

    | Cost-sensitive, Pusher-compatible | **Soketi** |

    | Custom protocol or niche requirement | **Ratchet** |

    For most Laravel projects starting today, **Reverb is the default**. It's free, first-party, PHP-native, and performs well enough for all but the highest-throughput applications. Start with Reverb. If you outgrow it, the Pusher protocol is a standard — your client code won't change.

    All Posts