Building Realtime APIs with WebSockets and Laravel Reverb

Khimananda Oli 8 min read Programming and Languages
Building Realtime APIs with WebSockets and Laravel Reverb

By Khimananda Oli | Last reviewed: August 2026

Many Laravel teams still rely on managed services like Pusher for broadcasting, but rising costs and data residency requirements often force a migration to self-hosted infrastructure. Building realtime APIs with WebSockets and Laravel Reverb provides a first-party, high-performance alternative that integrates natively with the Laravel ecosystem while keeping your infrastructure under your control. This guide walks through the exact configuration, Nginx reverse proxy setup, and security hardening required to run Reverb reliably in production.

What is Laravel Reverb and how does it enable building realtime APIs?

Laravel Reverb is a high-performance WebSocket server written in PHP specifically designed for the Laravel framework. Unlike older community-maintained packages, Reverb uses non-blocking I/O and ReactPHP to handle thousands of concurrent connections within a standard Laravel application process. When you are building realtime APIs with WebSockets and Laravel Reverb, you are essentially running a dedicated event loop alongside your traditional HTTP application that speaks the same protocol as Pusher but lives entirely on your own servers.

Laravel AppHTTP / QueueReverb ServerWebSocket :8080Browser / MobileLaravel EchoBroadcast EventWS Frame
High-level architecture for building realtime APIs with WebSockets and Laravel Reverb showing event flow from backend to client.

The primary advantage here is operational consistency. You do not need to learn Node.js or manage a separate Go-based WebSocket service. Your existing team can debug, extend, and monitor the realtime layer using the same tools they use for the rest of the application. For teams in Nepal or regions where data sovereignty matters, self-hosting ensures no user data leaves your controlled infrastructure. If you are new to optimizing the underlying stack, reviewing Laravel performance optimization techniques will help ensure your main application does not bottleneck the broadcast dispatch cycle.

How do you install and configure Laravel Reverb for production?

Installation is straightforward via Composer, but production configuration requires deliberate choices about environment variables and resource limits. Run composer require laravel/reverb followed by php artisan reverb:install. This publishes the configuration file and adds the necessary broadcasting driver settings.

Critical Environment Variables

In production, never rely on default ports or keys. Set these explicitly in your .env:

REVERB_APP_ID=your-unique-app-id
REVERB_APP_KEY=your-secret-key
REVERB_APP_SECRET=your-app-secret
REVERB_HOST=0.0.0.0
REVERB_PORT=8080
REVERB_SCHEME=https
REVERB_WS_HOST=ws.yourdomain.com
REVERB_WS_PORT=443
  • REVERB_HOST=0.0.0.0: Binds to all interfaces so Nginx can proxy traffic. Never expose this port directly to the public internet.
  • REVERB_SCHEME & WS_PORT: These tell Laravel Echo how to connect from the browser. Even though Reverb listens on 8080 internally, clients should always connect over 443 via your reverse proxy.
  • Memory Limits: Reverb is memory-intensive per connection. On a 4GB VPS, expect to handle roughly 5,000–8,000 concurrent connections comfortably. Monitor RSS usage closely.

For local development environments, especially when using Docker, refer to the local Laravel dev with Sail guide to correctly map the WebSocket port without conflicting with other services.

How do you configure Nginx as a reverse proxy for WebSocket traffic?

This is where most deployments fail. Nginx must be configured to upgrade HTTP connections to WebSocket protocol and maintain long-lived connections without buffering. Without this, clients will disconnect every 60 seconds or fail to handshake entirely.

server {
    listen 443 ssl http2;
    server_name ws.yourdomain.com;

    ssl_certificate     /etc/letsencrypt/live/ws.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ws.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Critical for WebSocket stability
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
        proxy_buffering off;
        proxy_cache off;
    }
}

The proxy_read_timeout value of 86400 seconds (24 hours) prevents Nginx from closing idle connections prematurely. WebSocket connections are persistent by nature; if Nginx applies its default 60-second timeout, your users will experience constant reconnection loops. Also note proxy_buffering off; — buffering breaks the streaming nature of WebSocket frames and causes message delivery delays.

ClientNginxReverbGET /app/key HTTP/1.1Upgrade: websocketProxy Pass + Headers101 Switching Protocols101 Response to ClientPersistent WS Frames
WebSocket upgrade sequence through Nginx when building realtime APIs with WebSockets and Laravel Reverb.

How do you manage the Reverb process with systemd?

Never run php artisan reverb:start inside a screen session or manually in production. Use systemd to ensure automatic restarts, log management, and resource constraints. Create /etc/systemd/system/reverb.service:

[Unit]
Description=Laravel Reverb WebSocket Server
After=network.target redis-server.service

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/bin/php /var/www/html/artisan reverb:start --host=0.0.0.0 --port=8080
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
Environment="APP_ENV=production"

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/var/www/html/storage/logs

[Install]
WantedBy=multi-user.target

Enable and start with systemctl enable --now reverb.service. The Restart=always directive is non-negotiable; PHP processes can crash under memory pressure or malformed frames, and automatic recovery is essential for uptime. For teams managing multiple services, understanding systemd services and timers provides deeper context on dependency ordering and journal logging.

How does Laravel Reverb compare to Pusher and Soketi?

Choosing the right broadcaster depends on your team's operational capacity, budget, and compliance needs. Here is a practical comparison based on real-world deployment characteristics in 2026:

CriteriaLaravel ReverbPusherSoketi
Cost at ScaleServer cost only (~$20/mo VPS)$50–$500+/mo tieredServer cost only
Data ResidencyFull control (Nepal/local OK)US/EU/SYD regions onlyFull control
Ecosystem IntegrationNative Laravel (first-party)Official SDK, maturePusher-compatible API
Operational OverheadModerate (you manage daemon)Zero (fully managed)Moderate (Node.js runtime)
Max Connections (Single Node)~10K–20K (PHP 8.4+)Unlimited (managed)~30K–50K (C++ core)
Debugging EaseStandard Laravel toolingDashboard + support ticketsRequires Node.js expertise

For most Laravel shops, especially those already running their own infrastructure, Reverb offers the best balance of cost, integration, and control. Soketi wins on raw connection density per node due to its C++ foundation, but introduces a second runtime to maintain. Pusher remains valid for teams with zero ops capacity or unpredictable traffic spikes where auto-scaling is worth the premium.

How do you secure and monitor a production Reverb deployment?

Security for WebSocket servers differs from standard HTTP APIs because connections are long-lived and stateful. Apply these hardening measures:

  1. TLS Everywhere: Never serve WebSocket traffic over plain TCP in production. Terminate TLS at Nginx and use internal HTTP only between Nginx and Reverb on localhost.
  2. Rate Limiting: Configure Reverb's built-in rate limiter in config/reverb.php to prevent abuse. A good starting point is 10 messages per second per connection.
  3. Authentication: Always validate channel subscriptions via Laravel's broadcasting auth endpoint. Never allow unauthenticated access to private channels.
  4. Firewall Rules: Block external access to port 8080 at the OS level using UFW or cloud security groups. Only Nginx should reach Reverb.
  5. Monitoring: Expose Reverb's metrics endpoint and scrape it with Prometheus. Track concurrent connections, message throughput, and memory usage. Refer to Prometheus metrics monitoring fundamentals for setting up effective alerts before saturation occurs.
Production Security LayersTLS TerminationNginx :443OS FirewallBlock Ext :8080Auth + Rate LimitReverb ConfigReverb Daemonlocalhost:8080
Defense-in-depth model for securing Laravel Reverb in production environments.

Monitoring should focus on three signals: connection count trend, message queue latency, and memory growth rate. Set alerts at 80% of your tested capacity ceiling, not at absolute failure points. Memory leaks in PHP WebSocket servers typically manifest as gradual RSS growth over days; track this with a simple systemd timer that logs ps -o rss= -p $(pgrep reverb) hourly to detect drift before OOM kills occur.

Next Steps for Production Readiness

Building realtime APIs with WebSockets and Laravel Reverb gives you full ownership of your event infrastructure, but that ownership demands disciplined operations. Start with a staging deployment that mirrors production Nginx and systemd configurations exactly. Load test with tools like Artillery or k6 to establish your true connection ceiling on your specific hardware before going live. Document your scaling runbook: when to add nodes, how to drain connections gracefully during deploys, and where to find logs when things break at 2 AM. If you need help architecting or auditing your realtime stack for production, reach out to discuss your specific requirements.

Frequently Asked Questions

Reverb is a first-party WebSocket server for Laravel. It eliminates third-party API costs by running directly on your infrastructure while maintaining full compatibility with existing Laravel broadcasting drivers and client libraries.

Run composer require laravel/reverb then php artisan reverb:install. This publishes the configuration file, adds necessary environment variables, and sets up the default WebSocket server settings automatically for immediate development use.

Yes. Reverb uses Redis pub/sub to synchronize messages across multiple server instances. Configure your Redis connection in config/reverb.php to enable seamless message broadcasting across distributed cloud or containerized deployments without custom code.

PHP 8.2+, Laravel 11+, and a persistent process manager like Supervisor. Production deployments require at least 512MB RAM per worker and an open TCP port, typically 8080, for WebSocket connections.

Yes, completely free and open source. You only pay for your own server resources, unlike Pusher or Ably which charge monthly fees based on message volume and concurrent connection counts.

Reverb uses standard Laravel broadcasting auth endpoints. Define channel authorization logic in routes/channels.php using Broadcast::channel. The server validates user sessions via cookies or tokens before allowing subscription to private or presence channels.

Absolutely. Use the official laravel-echo npm package with the reverb connector. It provides identical API syntax to Pusher, requiring only a host and port change in your Echo configuration for frontend integration.

Default limits depend on PHP memory and event loop capacity. A single Reverb worker typically handles 10,000 concurrent connections. Scale horizontally using Redis and load balancers to support higher traffic volumes in production environments.

Check php artisan reverb:serve logs and browser DevTools Network tab for handshake errors. Verify CORS settings in config/reverb.php match your frontend domain and ensure firewall rules allow traffic on the configured WebSocket port.

No. Terminate SSL at your reverse proxy layer using Nginx or Caddy. Configure the proxy to forward WebSocket upgrade headers to the internal Reverb port, keeping the application server behind a secure edge.

Reverb matches Socket.io for typical Laravel app loads under 50k concurrent users. Native PHP async I/O reduces context switching overhead when your stack already relies heavily on Laravel services, caching, and database models.

Clients automatically attempt reconnection with exponential backoff via Laravel Echo. Configure Supervisor or systemd to restart the reverb:serve process immediately upon failure to minimize downtime and maintain high availability for realtime features.

Yes. Dispatch broadcastable events from queued jobs normally. Reverb listens to the same Redis queue driver, ensuring events triggered asynchronously reach connected clients without blocking HTTP requests or requiring synchronous execution.

Expose the /health endpoint or use php artisan reverb:status. Integrate metrics into Prometheus or Datadog to track active connections, message throughput, and memory usage for proactive alerting and capacity planning.

Yes. Running Reverb alongside Octane via Swoole or RoadRunner improves throughput significantly. Ensure shared state is managed through Redis since both servers operate as long-lived processes with persistent memory states.