laravelwebsocketsdevopsgo

Relay WebSocket: alternativa a Reverb sin PHP

Relay WebSocket: La Alternativa Standalone a Laravel Reverb

Si trabajas con Laravel y necesitas WebSockets en tiempo real, probablemente conoces Laravel Reverb. Es una solución excelente, pero tiene una limitación importante: requiere que una aplicación Laravel esté ejecutándose constantemente solo para hostear el servidor WebSocket.

¿Qué pasa si quieres una solución más ligera, sin dependencias PHP, sin Composer, sin necesidad de mantener una instancia de Laravel solo para esto? Aquí es donde entra Relay, un servidor WebSocket open source escrito en Go que es compatible con Pusher y puede ejecutarse como un binario standalone.

En este artículo exploraremos qué es Relay, cómo configurarlo con tu aplicación Laravel, y cuándo deberías considerarlo sobre Reverb.

¿Qué es Relay y por qué es diferente?

Relay es un servidor WebSocket escrito en Go que mantiene compatibilidad con el protocolo Pusher. Esto significa que puedes usar la misma forma que usas Pusher o Reverb en Laravel, pero apuntando a tu instancia de Relay.

La diferencia fundamental es que Relay no necesita PHP ni Laravel. Es un binario que descargas, configuras y ejecutas. Puedes ponerlo en:

  • Un servidor dedicado
  • Una máquina Linux barata
  • Un contenedor Docker
  • Tu VPS existente (incluso el mismo que tu app Laravel)

Esto lo hace ideal para:

  • Proyectos pequeños/medianos donde no justifica tener una instancia Laravel completa solo para WebSockets
  • Infraestructura minimalista donde quieres menos dependencias
  • Hosting compartido donde no puedes ejecutar múltiples procesos PHP

Comparativa: Relay vs Reverb vs Pusher

Antes de decidir, aquí está la comparativa técnica:

AspectoRelayReverbPusher
LenguajeGoPHP (Laravel)SaaS
InstalaciónBinario standaloneArtisan commandNada (SaaS)
DependenciasNingunaLaravel appInternet
CostoGratis (open source)Gratis (incluido)Desde $49/mes
Self-hostedNo
EscalabilidadHorizontalVerticalIlimitada
CompatibilidadPusher APIPusher APIPusher API

Instalando y configurando Relay

Paso 1: Descargar Relay

Ve a https://github.com/relayprotocol/relay y descarga el binario para tu sistema operativo:

# En Linux x64
wget https://github.com/relayprotocol/relay/releases/download/v1.0.0/relay-linux-amd64
chmod +x relay-linux-amd64

# En Mac
wget https://github.com/relayprotocol/relay/releases/download/v1.0.0/relay-darwin-amd64
chmod +x relay-darwin-amd64

Paso 2: Configurar el archivo .env de Laravel

Actualiza tu .env para usar Relay:

# Cambiar de driver de broadcast
BROADCAST_DRIVER=pusher

# Credenciales de Relay (debes generarlas)
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_APP_CLUSTER=mt1

# Host donde corre Relay
PUSHER_HOST=localhost
PUSHER_PORT=6001
PUSHER_SCHEME=http

Paso 3: Crear archivo de configuración de Relay

Crea un archivo relay-config.json:

{
  "port": 6001,
  "appId": "your-app-id",
  "appKey": "your-app-key",
  "appSecret": "your-app-secret",
  "debug": false,
  "maxConnections": 10000,
  "authentication": {
    "enabled": true,
    "timeout": 30
  },
  "cors": {
    "enabled": true,
    "origins": ["http://localhost:3000", "http://localhost:8000"]
  },
  "ssl": {
    "enabled": false,
    "certPath": "/path/to/cert.pem",
    "keyPath": "/path/to/key.pem"
  }
}

Paso 4: Ejecutar Relay

./relay-linux-amd64 --config relay-config.json

Deberías ver algo como:

2026-04-14 10:30:45 [INFO] Relay WebSocket Server started on :6001
2026-04-14 10:30:45 [INFO] Listening for connections...

Usando Relay en tu aplicación Laravel

La belleza de usar Relay es que el código en Laravel es idéntico al de Pusher o Reverb. No necesitas cambiar nada en tu código si ya estabas usando broadcast().

Broadcasting un evento

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class MessageSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    public function __construct($message)
    {
        $this->message = $message;
    }

    public function broadcastOn()
    {
        return new Channel('chat');
    }

    public function broadcastAs()
    {
        return 'message.sent';
    }
}

En tu controlador

<?php

namespace App\Http\Controllers;

use App\Events\MessageSent;

class ChatController extends Controller
{
    public function sendMessage(Request $request)
    {
        $message = $request->validate(['message' => 'required|string']);
        
        // Broadcast el evento
        broadcast(new MessageSent($message['message']));
        
        return response()->json(['success' => true]);
    }
}

En tu JavaScript (Blade o Vue)

// Usando Laravel Echo (que funciona con cualquier servidor Pusher-compatible)
Echo.channel('chat')
    .listen('message.sent', (e) => {
        console.log('Nuevo mensaje:', e.message);
        addMessageToUI(e.message);
    });

Autenticación privada con Relay

Para canales privados, Relay necesita validar que el usuario tiene permisos:

// routes/channels.php
Broadcast::channel('chat.{id}', function ($user, $id) {
    // Verificar que el usuario puede acceder a este chat
    return $user->id === (int)$id;
});

Relay hará una solicitud POST a tu aplicación Laravel para validar esto:

// routes/api.php
Route::post('/broadcasting/auth', function (Request $request) {
    return Broadcast::auth($request);
});

Optimizando Relay en producción

1. Usar SSL/TLS

Si tu app está en HTTPS, Relay también debe estar en HTTPS:

{
  "ssl": {
    "enabled": true,
    "certPath": "/etc/letsencrypt/live/example.com/fullchain.pem",
    "keyPath": "/etc/letsencrypt/live/example.com/privkey.pem"
  }
}

2. Ejecutar como servicio systemd

Crea /etc/systemd/system/relay.service:

[Unit]
Description=Relay WebSocket Server
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/relay
ExecStart=/opt/relay/relay-linux-amd64 --config relay-config.json
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Luego:

sudo systemctl daemon-reload
sudo systemctl enable relay
sudo systemctl start relay
sudo systemctl status relay

3. Monitorear conexiones

Relay expone un endpoint /metrics (si está habilitado en config) para ver estadísticas:

curl http://localhost:6001/metrics

4. Usar Nginx como proxy reverso

Si quieres agregar caché, rate limiting, o balanceo de carga:

upstream relay {
    server localhost:6001;
}

server {
    listen 80;
    server_name ws.example.com;

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

Cuándo usar Relay vs Reverb

Usa Relay si:

  • Quieres minimizar dependencias en producción
  • Tienes un VPS pequeño con recursos limitados
  • No necesitas las integraciones avanzadas de Reverb
  • Prefieres un binario simple sin complejidad PHP
  • Quieres hostear múltiples apps con un solo servidor WebSocket

Usa Reverb si:

  • Ya estás cómodo con el ecosistema Laravel
  • Necesitas integración profunda con Laravel (queues, eventos, etc.)
  • Quieres soporte oficial de Laravel
  • Tu app es muy compleja y los WebSockets son una pequeña parte

Troubleshooting común

Conexiones rechazadas

Connection refused on :6001

Verifica que Relay está ejecutándose y escuchando:

netstat -tlnp | grep 6001
# o
lsof -i :6001

CORS errors

Actualiza el relay-config.json con los orígenes correctos:

{
  "cors": {
    "enabled": true,
    "origins": ["https://example.com", "https://app.example.com"]
  }
}

Autenticación fallida

Asegúrate de que tu ruta de broadcasting auth devuelve respuesta JSON válida:

// routes/api.php debe estar registrada ANTES de la ruta de broadcast auth
Route::post('/broadcasting/auth', function (Request $request) {
    return Broadcast::auth($request);
})->middleware('auth:sanctum');

Puntos clave

  • Relay es un servidor WebSocket Go que no requiere PHP ni Laravel, ideal para infraestructura minimalista
  • Compatible con Pusher, por lo que el código Laravel no cambia; solo cambia la configuración
  • Instalación simple: descargar binario, configurar JSON, ejecutar como servicio
  • Perfectamente útil para proyectos medianos que no justifican Pusher SaaS ni Reverb overkill
  • Puedes auto-hostear gratis o usar su servicio en la nube si prefieres
  • Requiere validación manual de canales privados a través de endpoints POST a tu app
  • En producción: usa SSL, systemd, y Nginx como proxy reverso para máxima confiabilidad
  • Menos overhead que Reverb porque no hay proceso PHP adicional ejecutándose