Desarrollo y bases de datos

WebSockets en Laravel: Reverb, Pusher y alternativas

Revisado el 11 min de lectura laravel websockets broadcasting pusher

Con el broadcasting de Laravel, el servidor avisa al navegador en el momento en que pasa algo: una notificación, un mensaje de chat, un pedido que cambia de estado. En el navegador escucha Laravel Echo; entre los dos hace falta un servidor de WebSockets que mantenga abierta la conexión con cada visitante. Ese servidor puede ser Reverb, si lo alojas tú, o un servicio compatible con el protocolo de Pusher, que Laravel soporta de serie.

En el hosting usamos la segunda opción: tu aplicación sigue aquí y las conexiones de los navegadores las atiende el servicio externo.

Por qué Reverb no funciona en el hosting

Reverb es un servidor que se queda en marcha y recibe las conexiones de los navegadores. Para que lleguen hace falta una de dos cosas: un puerto propio abierto a internet o que el servidor web le pase las conexiones WebSocket del 443. En un servidor compartido ninguna de las dos se puede ofrecer bien a cada cuenta: un puerto no se puede compartir entre cuentas ni reservar a una, muchas redes de empresas y administraciones solo dejan salir por el 443, y el proxy del servidor web es común a todas las webs. Por eso no ofrecemos Reverb, ni Soketi ni otros servidores de WebSockets propios, aunque puedas arrancarlos como proceso persistente.

Cómo funciona con un servicio externo

Laravel en el hosting  --HTTPS-->  servicio de WebSockets  <--WSS--  navegador con Echo

Cuando tu aplicación emite un evento, PHP hace una petición HTTPS al servicio. El servicio lo reparte a los navegadores conectados al canal. Los navegadores se conectan directamente al servicio, no al hosting, así que no consumen procesos ni conexiones de tu cuenta.

Comparativa

Precios y límites comprobados el 11 de octubre de 2026. Cambian a menudo: confírmalos en la web de cada servicio antes de decidir.

Lo que más pesa es el número de conexiones simultáneas: cada pestaña o pantalla con Echo abierta ocupa una. Los mensajes se cuentan por entrega: un evento que reciben 150 pantallas consume 151 mensajes.

Ably (recomendado)

  • Gratis: 200 conexiones simultáneas y 6 millones de mensajes al mes.
  • De pago: desde 29 $/mes más el uso, con hasta 10.000 conexiones.
  • Europa: guardar los datos solo en la UE es una opción del plan Enterprise.
  • En Laravel: driver ably incluido en Laravel, o el broadcaster oficial ably/laravel-broadcaster. En el navegador, Echo con el adaptador del protocolo de Pusher.

Es el plan gratuito más amplio de un servicio maduro: con 200 conexiones cabe, por ejemplo, un centro con un centenar largo de pantallas.

Pusher Channels

  • Gratis: 100 conexiones simultáneas y 200.000 mensajes al día.
  • De pago: desde 49 $/mes, con 500 conexiones y 1 millón de mensajes al día.
  • Europa: cluster eu, en Irlanda.
  • En Laravel: driver pusher, con php artisan install:broadcasting --pusher.

Es el camino más directo, el que usa la documentación de Laravel, y basta si no pasas de 100 conexiones a la vez.

Otras opciones compatibles con Pusher

PieSocket (gratis hasta 200 conexiones) y Vask (desde 10 $/mes por 500 conexiones) hablan el protocolo de Pusher, así que se configuran como Pusher cambiando el host. Son servicios más jóvenes y no publican dónde guardan los datos: pruébalos antes de usarlos en producción.

Qué necesita tu cuenta

  • Peticiones HTTPS salientes desde PHP, que el hosting permite. No hace falta abrir puertos ni instalar nada en el servidor.
  • Node.js para compilar Echo con Vite, desde el Gestor de paquetes. Deploy+ lo instala si tu script lo usa.
  • Un worker de colas si tus eventos implementan ShouldBroadcast: Laravel los envía desde la cola, y sin un worker en marcha llegan tarde o no llegan. En Avanza, Max y Elástico, crea un Worker de colas en procesos persistentes. En Inicia y Webmaster, implementa ShouldBroadcastNow: el evento se envía en la misma petición, sin cola, a cambio de que esa petición espere la respuesta del servicio. Una cola procesada por el scheduler cada minuto no sirve para tiempo real.

No necesitas Redis para el broadcasting.

Configurar Ably

  1. Crea una cuenta en Ably, una aplicación y una API key. Tiene la forma xxxx.yyyy:zzzz.

  2. En los ajustes de la aplicación, dentro de Protocol Adapter Settings, activa la compatibilidad con el protocolo de Pusher: Echo se conecta a Ably con pusher-js.

  3. En tu proyecto, en local:

    php artisan install:broadcasting --ably
    

    Si prefieres hacerlo a mano, composer require ably/ably-php instala el SDK de PHP.

  4. En el .env de producción:

    BROADCAST_CONNECTION=ably
    ABLY_KEY="xxxx.yyyy:zzzz"
    VITE_ABLY_PUBLIC_KEY="xxxx.yyyy"
    

    VITE_ABLY_PUBLIC_KEY es solo la parte de la clave anterior a los dos puntos. La clave completa no debe ir en ninguna variable VITE_.

  5. Configura Echo con el adaptador de Pusher de Ably:

    import Echo from 'laravel-echo';
    import Pusher from 'pusher-js';
    window.Pusher = Pusher;
    
    window.Echo = new Echo({
        broadcaster: 'pusher',
        key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
        wsHost: 'main.pusher.ably.net',
        wsPort: 443,
        forceTLS: true,
        disableStats: true,
        enabledTransports: ['ws', 'wss'],
    });
    
  6. Despliega y comprueba los eventos en la consola de tu aplicación en Ably.

Ably mantiene además su propio broadcaster para Laravel, ably/laravel-broadcaster, con funciones propias de su plataforma. Si lo usas, sigue su documentación para la parte del navegador.

Configurar Pusher Channels

  1. Crea una cuenta en Pusher y una aplicación de Channels en el cluster eu. En App Keys tienes app_id, key y secret.

  2. En tu proyecto, en local, instala el broadcasting:

    php artisan install:broadcasting --pusher
    

    El comando pide las credenciales, instala el SDK de PHP (pusher/pusher-php-server), Laravel Echo y pusher-js, crea routes/channels.php y deja Echo configurado. Guarda los cambios en tu repositorio.

  3. En el .env de producción (con Deploy+, desde el menú del repositorio, Editar .env):

    BROADCAST_CONNECTION=pusher
    
    PUSHER_APP_ID="tu_app_id"
    PUSHER_APP_KEY="tu_key"
    PUSHER_APP_SECRET="tu_secret"
    PUSHER_HOST=
    PUSHER_PORT=443
    PUSHER_SCHEME="https"
    PUSHER_APP_CLUSTER="eu"
    
    VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
    VITE_PUSHER_HOST="${PUSHER_HOST}"
    VITE_PUSHER_PORT="${PUSHER_PORT}"
    VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
    VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
    

    Las variables VITE_ acaban dentro del JavaScript público: lleva la key, que es pública, pero nunca el secret.

  4. Comprueba la configuración de Echo que ha dejado el instalador. En su forma básica, para Pusher, es esta:

    import Echo from 'laravel-echo';
    import Pusher from 'pusher-js';
    window.Pusher = Pusher;
    
    window.Echo = new Echo({
        broadcaster: 'pusher',
        key: import.meta.env.VITE_PUSHER_APP_KEY,
        cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
        forceTLS: true,
    });
    
  5. Despliega. Las variables VITE_ se leen al compilar con npm run build: si las cambias después, vuelve a desplegar para que el JavaScript las recoja.

  6. Abre la web y la Debug Console de tu aplicación en Pusher: verás cada conexión y cada evento enviado.

Para canales privados o de presencia, autoriza a cada usuario en routes/channels.php. Laravel registra la ruta /broadcasting/auth que usa Echo para pedir esa autorización.

Emitir un evento

Un evento que se emite desde la cola:

namespace App\Events;

use App\Models\Pedido;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class PedidoActualizado implements ShouldBroadcast
{
    public function __construct(public Pedido $pedido) {}

    public function broadcastOn(): array
    {
        return [new PrivateChannel('pedidos.'.$this->pedido->user_id)];
    }
}

Sin un worker de colas en marcha, cambia ShouldBroadcast por ShouldBroadcastNow. En el navegador:

window.Echo.private(`pedidos.${userId}`)
    .listen('PedidoActualizado', (e) => console.log(e.pedido));

Si el evento no llega, revisa por orden: que BROADCAST_CONNECTION sea el del servicio, que la configuración no esté cacheada con valores antiguos (php artisan config:cache), que haya un worker procesando la cola, que la consola del servicio reciba el evento y que el navegador se conecte con la key correcta.

Te ayudamos a conectarlo

Si tu aplicación usaba Reverb en otro servidor, el cambio suele limitarse al .env, a la configuración de Echo y a un despliegue. Si necesitas ayuda, escríbenos desde el área de clientes.

Más sobre Laravel en el hosting en Instalar Laravel. Referencia: broadcasting en Laravel.

También te puede ayudar

¿Algo no cuadra o ha cambiado? Cuéntanoslo y lo revisamos.