Skip to content

Laravel Broadcasting — Real-Time Events with WebSockets

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Laravel Broadcasting. We cover key concepts, practical examples, and best practices to help you master this topic.

Laravel broadcasting enables real-time Websocket communication using Pusher, Reverb, or other drivers, with Laravel Echo on the frontend subscribing to events over channels.

What You'll Learn

By the end of this tutorial, you'll set up broadcasting with Reverb, define broadcast events, create public/private/presence channels, use Laravel Echo, and implement real-time features.

Why Broadcasting Matters

Real-time features like live chat, notifications, and collaborative editing require server-push capabilities that HTTP polling cannot efficiently provide.

Real-World Use

A collaboration platform broadcasts task updates to all team members. When a user completes a task, the event triggers a notification and updates the task board for all connected clients.

Broadcasting Path

flowchart LR
  A[Laravel Framework] --> B[Broadcasting]
  B --> C[Reverb]
  B --> D[Pusher]
  B --> E[Echo]
  B --> F[Channels]
  B --> G{You Are Here}
  style G fill:#f90,color:#fff

Broadcasting Configuration

Configure Reverb (Laravel's first-party WebSocket server).

composer require laravel/reverb
php artisan reverb:install
<?php
// config/broadcasting.php
"connections" => [
    "reverb" => [
        "driver" => "reverb",
        "key" => env("REVERB_APP_KEY"),
        "secret" => env("REVERB_APP_SECRET"),
        "app_id" => env("REVERB_APP_ID"),
        "options" => [
            "host" => env("REVERB_HOST", "localhost"),
            "port" => env("REVERB_PORT", 8080),
            "scheme" => env("REVERB_SCHEME", "http"),
        ],
        "client_options" => [],
    ],
],

Broadcast Events

Create and configure broadcastable events.

<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
class OrderShipped implements ShouldBroadcast {
    use Dispatchable, InteractsWithSockets;
    public function __construct(
        public Order $order,
    ) {}
    public function broadcastOn(): array {
        return [
            new PrivateChannel("orders.{$this->order->id}"),
            new Channel("admin.orders"),
        ];
    }
    public function broadcastWith(): array {
        return [
            "id" => $this->order->id,
            "status" => $this->order->status,
            "total" => $this->order->total,
        ];
    }
    public function broadcastAs(): string {
        return "order.shipped";
    }
}

Laravel Echo Client

Listen for events on the frontend.

import Echo from "laravel-echo";
import Pusher from "pusher-js";
window.Echo = new Echo({
    broadcaster: "reverb",
    key: import.meta.env.VITE_REVERB_APP_KEY,
    wsHost: import.meta.env.VITE_REVERB_HOST,
    wsPort: import.meta.env.VITE_REVERB_PORT,
    forceTLS: false,
    enabledTransports: ["ws", "wss"],
});
// Listen on private channel
Echo.private("orders.1")
    .listen(".order.shipped", (e) => {
        alert(`Order #${e.id} shipped!`);
    });
// Listen on public channel
Echo.channel("admin.orders")
    .listen(".order.shipped", (e) => {
        toastr.success(`Order ${e.id} shipped`);
    });

Presence Channels

Track connected users in real-time.

<?php
namespace App\Events;
use Illuminate\Broadcasting\PresenceChannel;
class UserTyping implements ShouldBroadcast {
    public function __construct(public string $roomId, public string $userName) {}
    public function broadcastOn(): array {
        return [new PresenceChannel("chat.{$this->roomId}")];
    }
}
// Frontend
Echo.join("chat.room1")
    .here((users) => {
        console.log("Connected users:", users);
    })
    .joining((user) => {
        console.log("User joined:", user.name);
    })
    .leaving((user) => {
        console.log("User left:", user.name);
    })
    .listen(".typing", (e) => {
        showTypingIndicator(e.userName);
    });

Channel Authorization

Authorize private and presence channels.

<?php
// routes/channels.php
use App\Models\Order;
use App\Models\User;
Broadcast::channel("orders.{orderId}", function (User $user, int $orderId) {
    $order = Order::findOrFail($orderId);
    return $user->id === $order->user_id || $user->isAdmin();
});
Broadcast::channel("chat.{roomId}", function (User $user, string $roomId) {
    return ["id" => $user->id, "name" => $user->name, "avatar" => $user->avatar_url];
});

Common Mistakes

1. Broadcasting Sensitive Data

Broadcast events send data to all subscribers. Never include passwords, tokens, or PII.

2. Not Using Private Channels for User-Specific Data

Using public channels for private data exposes it to unauthorized users.

3. Forgetting broadcastAs for Custom Event Names

Without broadcastAs, the event class name is used. Custom names are cleaner for frontend.

4. Broadcasting Too Many Events

High-frequency events overwhelm the WebSocket server. Throttle with debouncing.

5. Not Securing WebSocket Connections

WebSocket endpoints should use WSS in production and require authentication where needed.

Practice Questions

1. What is the difference between Channel and PrivateChannel?

Channel is public access. PrivateChannel requires authorization.

2. What is a presence channel?

A private channel that tracks which users are currently connected.

3. How do you customize the broadcast event name?

Use broadcastAs() method and prefix with a dot in Echo.

4. What does broadcastWith() control?

The data sent to clients when the event is broadcast.

5. Challenge: Create a real-time notification system.

<?php
class NotificationSent implements ShouldBroadcast {
    public function broadcastOn(): array {
        return [new PrivateChannel("notifications.{$this->userId}")];
    }
    public function broadcastAs(): string {
        return "notification.sent";
    }
}
// Listen
Echo.private("notifications.1")
    .listen(".notification.sent", (e) => showNotification(e));

FAQ

What is Reverb?

Laravel Reverb is a first-party WebSocket server for real-time broadcasting.

Can I use Pusher instead of Reverb?

Yes. Pusher works out of the box with Laravel broadcasting.

What is Laravel Echo?

A JavaScript library that subscribes to channels and listens for broadcast events.

How do I broadcast from a controller?

Use event(new OrderShipped($order)) or OrderShipped::dispatch($order).

Can I broadcast without a queue?

Yes, but queued broadcasting is recommended for performance.

Mini Project: Real-Time Chat Application

Implement a real-time chat with presence channels.

<?php
class MessageSent implements ShouldBroadcast {
    public function broadcastOn(): array {
        return [new PresenceChannel("chatroom.{$this->chatroomId}")];
    }
    public function broadcastAs(): string {
        return "message.sent";
    }
}

What's Next

Laravel Notifications Laravel Queues Deep Laravel Cache Deep

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro