
Table of Contents
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.
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.
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:
| Criteria | Laravel Reverb | Pusher | Soketi |
|---|---|---|---|
| Cost at Scale | Server cost only (~$20/mo VPS) | $50–$500+/mo tiered | Server cost only |
| Data Residency | Full control (Nepal/local OK) | US/EU/SYD regions only | Full control |
| Ecosystem Integration | Native Laravel (first-party) | Official SDK, mature | Pusher-compatible API |
| Operational Overhead | Moderate (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 Ease | Standard Laravel tooling | Dashboard + support tickets | Requires 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:
- 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.
- Rate Limiting: Configure Reverb's built-in rate limiter in
config/reverb.phpto prevent abuse. A good starting point is 10 messages per second per connection. - Authentication: Always validate channel subscriptions via Laravel's broadcasting auth endpoint. Never allow unauthenticated access to private channels.
- Firewall Rules: Block external access to port 8080 at the OS level using UFW or cloud security groups. Only Nginx should reach Reverb.
- 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.
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.