Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

WebSockets for Real-Time APIs

By Kokil Thapa | Last reviewed: September 2026

Your booking dashboard shows stale inventory. Your chat widget lags by ten seconds. Your order tracker hammers the server every two seconds with REST polling. WebSockets for Real-Time APIs solve this by keeping one TCP connection open and letting the server push events the moment state changes. On production API development projects, I treat WebSockets as an extension of the API layer—not a separate toy channel. This guide covers when they beat polling, how the handshake works, and how to ship them with Laravel 13.x and PHP 8.3+ in 2026.

What Are WebSockets and How Do They Differ from REST for Real-Time APIs?

REST over HTTP is request-response. The client asks; the server answers; the connection closes. That model works for CRUD, file uploads, and paginated lists. It fails when the client needs continuous updates.

WebSockets start as HTTP and upgrade to a full-duplex protocol defined in RFC 6455. After the handshake, both sides send framed messages without reopening TCP. Latency drops from hundreds of milliseconds to single digits on a healthy network.

REST Polling vs WebSockets for Real-Time APIsREST PollingNew HTTP request every N secondsHigh overhead, delayed updatesEasy to cache and debugWebSocket ChannelOne persistent connectionServer pushes on changeLow latency, statefulBest Fit for Real-Time APIsLive order status, chat, notifications, inventory syncREST still owns create, read, update, delete endpoints
WebSockets for Real-Time APIs replace repeated polling with a single bidirectional channel while REST handles standard CRUD operations.

The practical split I use on client projects: REST creates and mutates resources. WebSockets notify subscribers that something changed. A user submits a payment via POST. The WebSocket channel broadcasts order.paid to the admin dashboard. Mixing both keeps your API predictable and your UI responsive.

Compare the three common push patterns in the table below. Each has a place in a modern stack documented in our REST API design guide.

PatternDirectionConnectionBest Use Case
Short pollingClient pullsRepeated HTTPLegacy dashboards, low-frequency checks
Server-Sent Events (SSE)Server pushes onlyOne HTTP streamLive feeds, progress bars, one-way alerts
WebSocketsBoth directionsUpgraded TCPChat, collaborative editing, live game state

SSE is simpler when the browser only listens. WebSockets win when the client must send frequent messages back—typing indicators, cursor positions, or ack receipts. For a trek booking platform with live availability, bidirectional channels let staff lock seats while customers watch counts update.

When Should You Use WebSockets for Real-Time APIs Instead of Polling?

Not every page needs a socket. I add WebSockets when update frequency, latency sensitivity, or bidirectional traffic crosses a clear threshold.

  • High update frequency: More than one poll per five seconds per client wastes bandwidth and database load.
  • Low latency requirements: Payment confirmations, delivery tracking, and support chat need sub-second delivery.
  • Bidirectional messaging: The client sends events as often as it receives them.
  • Many concurrent subscribers: One server event should fan out to hundreds of connected clients instantly.

Skip WebSockets when updates are rare, when you need aggressive HTTP caching, or when corporate proxies block long-lived connections. A quarterly report page belongs on REST. A live auction belongs on WebSockets.

On legal-tech portals I have built, document upload status uses SSE or polling. Live case-status chat between client and lawyer uses WebSockets because both sides send messages in bursts. The Laravel WebSockets and Redis guide walks through that hybrid pattern in more detail.

How Does the WebSocket Handshake Work for Real-Time APIs?

Every WebSocket session begins as a normal HTTP request. The client sends an Upgrade header. The server responds with 101 Switching Protocols. After that, HTTP is done—the wire carries WebSocket frames.

WebSocket Handshake for Real-Time APIsClientBrowser or mobile appServerReverb or Node gatewayStep 1: HTTP GETUpgrade: websocket header sentStep 2: 101 ResponseConnection: Upgrade confirmedStep 3: Full-duplex JSON frames — no more HTTP overhead
The WebSocket handshake upgrades a standard HTTP request into a persistent channel for Real-Time API event delivery.

The client request looks like this:

GET /app/my-key?protocol=7&client=js&version=8.4.0 HTTP/1.1
Host: ws.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

The server validates the key, returns Sec-WebSocket-Accept, and the socket stays open. From here, messages are lightweight frames—often JSON payloads your API already uses. Validate incoming frames the same way you validate REST bodies. Use a JSON formatter during development to inspect event shapes before they hit production clients.

Frame structure and heartbeat

WebSocket frames carry text or binary data. Most Real-Time APIs use text frames with JSON. Add application-level ping/pong or rely on server heartbeat intervals to detect dead connections. Proxies and load balancers often kill idle sockets after 60 seconds unless you configure longer timeouts on your Linux server layer.

How Do You Implement WebSockets in Laravel for Production Real-Time APIs?

Laravel 13 ships with first-party broadcasting and Laravel Reverb as the WebSocket server. Reverb speaks the Pusher protocol, so existing Echo clients work without rewrites. PHP 8.3+ and Composer 2.10 are the baseline on new projects in 2026.

Laravel Reverb Real-Time API StackVue / AlpineLaravel Echo clientReverbWebSocket serverLaravel AppEvents and jobsRedis 8.10 Pub/SubSyncs broadcasts across Reverb nodesREST API writes data — WebSocket channel pushes the update
Laravel Reverb connects browser clients to your app through Redis-backed pub/sub for scalable WebSockets Real-Time APIs.

Install and configure Reverb on a Laravel 13 project:

  1. Install Reverb: composer require laravel/reverb
  2. Publish config: php artisan reverb:install
  3. Set BROADCAST_CONNECTION=reverb in .env
  4. Start the server: php artisan reverb:start
  5. Run a queue worker so broadcast events dispatch asynchronously

Define a broadcast event that implements ShouldBroadcast:

<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class OrderStatusUpdated implements ShouldBroadcast
{
    public function __construct(public Order $order) {}

    public function broadcastOn(): array
    {
        return [new Channel('orders.' . $this->order->id)];
    }

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

Fire the event after your REST controller updates the order:

public function updateStatus(UpdateOrderRequest $request, Order $order)
{
    $order->update(['status' => $request->validated('status')]);

    OrderStatusUpdated::dispatch($order);

    return response()->json($order);
}

On the client, Laravel Echo subscribes and reacts:

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'],
});

Echo.channel(`orders.${orderId}`)
    .listen('.order.status.updated', (event) => {
        updateStatusBadge(event.order.status);
    });

Our dedicated posts on Laravel Reverb and WebSockets and building Real-Time APIs with Reverb expand on channel naming, private channels, and presence rooms. Follow Laravel API best practices for the REST side that triggers these events.

Channel types matter for API design

Public channels suit open feeds—stock tickers, public auction bids. Private channels require authentication and fit user-specific data like order status. Presence channels track who is online—useful for collaborative document review on a law firm client portal. Name channels consistently: {resource}.{id} mirrors REST URL patterns and keeps authorisation logic predictable.

How Do You Secure and Scale WebSockets for Real-Time APIs?

WebSockets bypass your normal HTTP middleware stack after upgrade. Treat authentication and authorisation as first-class concerns from day one.

Authentication patterns

Never expose sensitive data on public channels. For private channels, Laravel Echo calls your /broadcasting/auth endpoint with the session cookie or Sanctum token. The server returns a signed auth payload. Reverb verifies the signature before subscribing the client.

Broadcast::channel('orders.{orderId}', function ($user, $orderId) {
    return $user->orders()->where('id', $orderId)->exists();
});

Cross-origin WebSocket connections need explicit CORS and cookie settings. Use SameSite=None; Secure when the WebSocket host differs from the API host. Review our API security checklist and Sanctum vs Passport guide for token strategies on SPA clients.

Horizontal scaling with Redis

A single Reverb process handles thousands of connections on modest hardware. Multiple app servers need Redis pub/sub so a broadcast from Server A reaches clients connected to Server B. Redis 8.10 as the broadcast driver is the standard pattern I deploy on Ubuntu 24 with PHP-FPM.

Scaling WebSockets for Real-Time APIsApp Server 1Laravel + queueApp Server 2Laravel + queueApp Server 3Laravel + queueRedis Pub/Sub HubBroadcasts sync all nodesReverb Node A500 clientsReverb Node B500 clients
Redis pub/sub lets multiple Reverb nodes deliver WebSockets for Real-Time APIs without siloed client connections.

Put Nginx or another reverse proxy in front of Reverb with WebSocket-aware config:

location /app {
    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_read_timeout 86400;
}

Rate-limit connection attempts at the edge. Apply rate limiting strategies to the REST endpoints that trigger broadcasts. A burst of fake order updates should not flood every connected dashboard.

How Do You Monitor and Debug WebSocket Connections in Production?

WebSocket failures are silent compared to HTTP 500 pages. Clients show stale UI while the socket reconnects in the background. Build observability into your Real-Time API from the start.

  • Connection metrics: Track active sockets, connect/disconnect rates, and auth failures per channel.
  • Event throughput: Count broadcasts sent, queue lag, and Redis publish latency.
  • Client reconnect logic: Echo reconnects automatically, but cap retry backoff to avoid thundering herds after deploys.
  • Structured logging: Log channel name, event type, and user ID—not full payloads with PII.

I wire Prometheus exporters alongside the patterns in our API monitoring guide. After Deployer 7 symlink swaps on production servers, reload PHP-FPM and restart Reverb so opcache and socket processes pick up new code. Stale Reverb workers are a common post-deploy bug I have hit on shared EC2 infrastructure.

Test WebSocket flows in CI with integration tests that hit /broadcasting/auth and assert event serialization. Load-test with tools like k6 WebSocket extensions before launch. A testing and optimization pass catches connection leaks that unit tests miss.

For eCommerce projects like Quick And Easy Nepalese Grocery, real-time delivery tracking depends on reliable reconnect after mobile network drops. Expose connection state in the UI so users know when they are viewing live data versus a cached snapshot.

Key Takeaways

  • Use WebSockets for Real-Time APIs when you need bidirectional, sub-second updates—not for occasional CRUD reads.
  • Keep REST for mutations; broadcast events after successful writes so your API contract stays clean.
  • Laravel Reverb with Redis 8.10 pub/sub scales WebSockets across multiple app and Reverb nodes on PHP 8.3+.
  • Authenticate private channels through /broadcasting/auth and never leak sensitive data on public channels.
  • Configure Nginx WebSocket proxy timeouts and monitor connection counts to catch silent failures early.
  • Plan client reconnect and queue-backed broadcasting before launch, not after users report stale dashboards.

People Also Ask

Are WebSockets better than REST for real-time data?

WebSockets are better for continuous, low-latency, bidirectional updates. REST remains better for stateless CRUD, caching, and standard HTTP tooling. Most production systems use both: REST writes data, WebSockets notify subscribers.

Can WebSockets work with Laravel API authentication?

Yes. Private and presence channels authenticate through Laravel's broadcasting auth endpoint using session cookies or Sanctum tokens. The server signs the subscription request before Reverb accepts the connection.

Do WebSockets increase server load compared to polling?

WebSockets reduce HTTP overhead and database reads from constant polling. They add memory per open connection and require a dedicated process like Reverb. For high-frequency updates, total load is usually lower than aggressive polling.

What happens when a WebSocket connection drops?

Laravel Echo reconnects automatically with exponential backoff. Design clients to refetch critical state over REST after reconnect so no events are missed during the gap. Idempotent event handlers prevent duplicate UI updates.

Ship Real-Time Features That Actually Work

WebSockets for Real-Time APIs are the right tool when your users expect live data—not refreshed pages. Start with a clear split: REST owns writes, WebSockets own notifications. Use Laravel Reverb on PHP 8.3+, back it with Redis, and lock down private channels before you expose customer data. If you want help architecting or deploying real-time features on an existing enterprise application, get in touch or browse the portfolio for shipped examples. Read more on the blog, explore web development services, or review building RESTful APIs with Laravel to complete your API stack.

Frequently Asked Questions

WebSockets use a single upgraded HTTP connection so the server pushes JSON events the moment state changes. REST still handles CRUD; WebSockets notify subscribers that something changed.

Yes for continuous, low-latency, bidirectional updates. REST remains better for stateless CRUD, caching, and standard HTTP tooling. Most production systems use both: REST writes, WebSockets notify.

Add WebSockets when updates happen more than once every five seconds per client, when you need sub-second delivery for payments or chat, when traffic is bidirectional, or when one server event must fan out to many subscribers instantly. Skip them for rare updates, pages that rely on aggressive HTTP caching, or environments where corporate proxies block long-lived connections. A quarterly report page belongs on REST; a live auction or delivery tracker belongs on WebSockets.

Every session starts as a normal HTTP request with Upgrade: websocket and Connection: Upgrade headers. The server validates Sec-WebSocket-Key, responds with 101 Switching Protocols and Sec-WebSocket-Accept, then HTTP is done. After that, both sides exchange lightweight framed messages, usually JSON matching your existing API payloads. Validate incoming frames the same way you validate REST bodies. Add application-level ping/pong or server heartbeats because proxies and load balancers often kill idle sockets after about 60 seconds unless you configure longer timeouts.

Server-Sent Events are server-to-client only over one HTTP stream—ideal for live feeds, progress bars, and one-way alerts. WebSockets are full-duplex over an upgraded TCP channel defined in RFC 6455, so both sides send messages without reopening connections. SSE is simpler when the browser only listens. WebSockets win when the client sends frequent messages back, such as typing indicators, cursor positions, or acknowledgment receipts. On legal-tech portals, document upload status fits SSE or polling; live client-lawyer chat fits WebSockets.

Laravel 13.x with PHP 8.3 or higher and Composer 2.10 on new projects in 2026.

Laravel 13 ships first-party broadcasting and Laravel Reverb as the WebSocket server. Install with composer require laravel/reverb, run php artisan reverb:install, set BROADCAST_CONNECTION=reverb in .env, and start the server with php artisan reverb:start. Run a queue worker so broadcast events dispatch asynchronously. Define events implementing ShouldBroadcast, fire them after REST controllers mutate data, and subscribe on the client with Laravel Echo using the reverb broadcaster. Reverb speaks the Pusher protocol, so existing Echo clients work without rewrites.

Yes. Private and presence channels authenticate through Laravel's /broadcasting/auth endpoint using session cookies or Sanctum tokens. The server returns a signed auth payload that Reverb verifies before subscribing the client.

WebSockets bypass normal HTTP middleware after the upgrade, so treat authentication and authorization as first-class concerns. Never expose sensitive data on public channels. For private channels, Laravel Echo calls /broadcasting/auth; the server checks channel authorization callbacks, such as verifying the user owns the order, before signing the subscription. Cross-origin WebSocket connections need explicit CORS and cookie settings—use SameSite=None; Secure when the WebSocket host differs from the API host. Rate-limit connection attempts at the edge and apply rate limiting to REST endpoints that trigger broadcasts.

A single Reverb process handles thousands of connections on modest hardware, but multiple app servers need Redis pub/sub so a broadcast from one server reaches clients connected to another. Redis 8.10 as the broadcast driver is the standard pattern on Ubuntu 24 with PHP-FPM. Put Nginx or another reverse proxy in front of Reverb with WebSocket-aware configuration, including Upgrade and Connection headers and a long proxy_read_timeout such as 86400 seconds. Without Redis pub/sub, client connections on different Reverb nodes stay siloed and miss events.

WebSockets reduce HTTP overhead and database reads from constant polling, which often wastes bandwidth when clients poll more than once every five seconds. They add memory per open connection and require a dedicated process like Reverb. For high-frequency updates, total load is usually lower than aggressive polling, but you must account for the persistent Reverb process and queue workers that dispatch broadcasts asynchronously.

Laravel Echo reconnects automatically with exponential backoff, but clients should refetch critical state over REST after reconnect so no events are missed during the gap. Idempotent event handlers prevent duplicate UI updates. Mobile network drops are common on delivery-tracking apps, so expose connection state in the UI so users know when they are viewing live data versus a cached snapshot. Cap retry backoff after deploys to avoid thundering herds of reconnecting clients.

Put Nginx in front of Reverb with WebSocket-aware settings: proxy_http_version 1.1, proxy_set_header Upgrade set to the incoming upgrade header, proxy_set_header Connection set to Upgrade, proxy_set_header Host preserved, and proxy_pass pointing to your Reverb port such as 127.0.0.1:8080. Set proxy_read_timeout high—86400 seconds in the article example—because default idle timeouts often kill sockets after 60 seconds. Without these headers, the upgrade handshake fails and clients fall back to stale polling behavior.

WebSocket failures are silent compared to HTTP 500 pages, so build observability from the start. Track active sockets, connect and disconnect rates, and auth failures per channel. Count broadcasts sent, queue lag, and Redis publish latency. Log channel name, event type, and user ID—not full payloads with PII. After Deployer 7 symlink swaps, reload PHP-FPM and restart Reverb so opcache and socket processes pick up new code. Test flows in CI against /broadcasting/auth and load-test with k6 WebSocket extensions before launch.

Public channels suit open feeds like stock tickers or public auction bids. Private channels require authentication and fit user-specific data such as order status. Presence channels track who is online, useful for collaborative document review on a law firm client portal. Name channels consistently using {resource}.{id} to mirror REST URL patterns and keep authorization logic predictable. On the client, subscribe with Echo.channel for public feeds and authenticated private channels for sensitive updates, listening for dot-prefixed event names like .order.status.updated.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: