Back to Blog
Blog/Architecture

Architecting Real-Time Order & Stock Sync: Integrating WebSockets, Laravel Echo & Redis in Production

How to eliminate HTTP polling bottlenecks and stream instantaneous stock updates and order status changes using Laravel Echo, Redis pub/sub, and Soketi WebSockets.

Akram Hafaiedh
Akram Hafaiedh
Full Stack Developer
2026-03-206 min read
// SYSTEM ARCHITECTURE PATTERN
PRODUCTION VERIFIED
TECHNICAL CASE STUDY

Architecting Real-Time Order & Stock Sync: Integrating WebSockets, Laravel Echo & Redis in Production

LARAVELREDISMULTI-TENANT

Architecting Real-Time Order & Stock Sync with WebSockets

In high-volume ERP and e-commerce platforms, multiple warehouse staff and sales reps update stock levels concurrently. Relying on HTTP polling to reflect stock adjustments causes server overhead and delayed inventory states.

Here is how we built a scalable event-driven architecture using Laravel WebSockets/Soketi, Redis Pub/Sub, and Laravel Echo + Vue 3 to push instantaneous inventory updates across tenant dashboards.


1. Broadcasting Domain Events in Laravel

Whenever a sales order is completed or stock adjustment occurs, dispatch a broadcastable event implement ShouldBroadcastNow:

php
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// app/Events/StockLevelUpdatedEvent.php
namespace App\Events;

use App\Models\Product;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class StockLevelUpdatedEvent implements ShouldBroadcastNow
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(
        public Product $product,
        public int $companyId
    ) {}

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

    public function broadcastAs(): string
    {
        return 'stock.updated';
    }

    public function broadcastWith(): array
    {
        return [
            'product_id' => $this->product->id,
            'name' => $this->product->name,
            'new_quantity' => $this->product->stock_quantity,
            'updated_at' => now()->toIso8601String(),
        ];
    }
}

2. Authenticating Private Workspace Channels

To ensure multi-tenant security, authorize channel access by matching the authenticated user's active company context:

php
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// routes/channels.php
use App\Models\User;

Broadcast::channel('company.{companyId}', function (User $user, int $companyId) {
    return (int) $user->active_company_id === (int) $companyId;
});

3. Listening to Live Updates in Vue 3

On the Vue 3 frontend, initialize Laravel Echo with WebSocket client credentials and listen to incoming event streams:

ts
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// composables/useStockWebSocket.ts
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
import { onMounted, onUnmounted } from 'vue';

window.Pusher = Pusher;

export function useStockWebSocket(companyId: number, onStockUpdated: (data: any) => void) {
    let echoInstance: Echo | null = null;

    onMounted(() => {
        echoInstance = 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 ?? 80,
            wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
            forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
            enabledTransports: ['ws', 'wss'],
        });

        echoInstance
            .private(class="text-emerald-500 dark:text-emerald-400 font-medium">`company.${companyId}`)
            .listen('.stock.updated', (eventData: any) => {
                console.log('Real-time stock update received:', eventData);
                onStockUpdated(eventData);
            });
    });

    onUnmounted(() => {
        if (echoInstance) {
            echoInstance.leaveChannel(class="text-emerald-500 dark:text-emerald-400 font-medium">`company.${companyId}`);
        }
    });
}

Replacing periodic HTTP polling with WebSocket event streaming reduced backend API load by 70% while guaranteeing sub-second stock synchronization across active team members.

Engineering Collaboration

Building a High-Scale SaaS or Complex System?

Let’s discuss your architecture, full-stack development, or system modernization needs.

Related Articles

// SYSTEM ARCHITECTURE PATTERN
PRODUCTION VERIFIED
TECHNICAL CASE STUDY

Monetizing API Quotas & Multi-Company Tier Gating: Designing Dynamic SaaS Pricing & Add-On Management

LARAVELREDISMULTI-TENANT
Architecture
2026-03-10•Architecture

Monetizing API Quotas & Multi-Company Tier Gating: Designing Dynamic SaaS Pricing & Add-On Management

Read Article
// SYSTEM ARCHITECTURE PATTERN
PRODUCTION VERIFIED
TECHNICAL CASE STUDY

Building Granular RBAC & Cascading Subscription Feature Gates in Multi-User SaaS

LARAVELREDISMULTI-TENANT
Architecture
2026-03-06•Architecture

Building Granular RBAC & Cascading Subscription Feature Gates in Multi-User SaaS

Read Article