DEV Community

丁久
丁久

Posted on • Originally published at dingjiu1989-hue.github.io

gRPC vs WebSocket: Real-Time Communication

This article was originally published on AI Study Room. For the full version with working code examples and related articles, visit the original post.

Introduction

Real-time communication is essential for modern applications--from chat and live dashboards to multiplayer gaming and financial trading platforms. gRPC and WebSocket represent two fundamentally different approaches to bidirectional streaming. gRPC builds on HTTP/2 with Protocol Buffers for typed, efficient RPCs. WebSocket provides a message-oriented protocol over a single TCP connection. This article compares them across the dimensions that matter for real-time application design.

Protocol Fundamentals

gRPC: HTTP/2 + Protocol Buffers

gRPC leverages HTTP/2 multiplexing and Protocol Buffers for typed, efficient communication:

// order.proto
syntax = "proto3";

package order;

service OrderService {
    // Unary RPC (request-response)
    rpc CreateOrder(CreateOrderRequest) returns (Order);

    // Server streaming (push events to client)
    rpc SubscribeOrders(OrderFilter) returns (stream Order);

    // Client streaming (upload batch)
    rpc BulkCreateOrders(stream CreateOrderRequest) returns (BulkResponse);

    // Bidirectional streaming (full duplex)
    rpc ProcessOrders(stream OrderAction) returns (stream OrderResult);
}

message Order {
    string id = 1;
    string user_id = 2;
    repeated LineItem items = 3;
    double total = 4;
    OrderStatus status = 5;
    google.protobuf.Timestamp created_at = 6;
}

message CreateOrderRequest {
    string user_id = 1;
    repeated LineItem items = 2;
}

message OrderFilter {
    repeated string statuses = 1;
}

message LineItem {
    string product_id = 1;
    int32 quantity = 2;
    double price = 3;
}

enum OrderStatus {
    PENDING = 0;
    CONFIRMED = 1;
    PROCESSING = 2;
    SHIPPED = 3;
    DELIVERED = 4;
    CANCELLED = 5;
}
Enter fullscreen mode Exit fullscreen mode

Server implementation in Go:

package main

import (
    "context"
    "log"
    "net"
    "google.golang.org/grpc"
    pb "path/to/proto/order"
)

type orderServer struct {
    pb.UnimplementedOrderServiceServer
}

// Bidirectional streaming
func (s *orderServer) ProcessOrders(
    stream pb.OrderService_ProcessOrdersServer,
) error {
    for {
        action, err := stream.Recv()
        if err != nil {
            return err
        }

        // Process order action
        result := &pb.OrderResult{
            OrderId: action.OrderId,
            Status:  pb.OrderStatus_PROCESSING,
            Message: "Order received and processing",
        }

        if err := stream.Send(result); err != nil {
            return err
        }
    }
}

func main() {
    lis, _ := net.Listen("tcp", ":50051")
    s := grpc.NewServer(
        grpc.MaxRecvMsgSize(4 * 1024 * 1024),    // 4MB
        grpc.MaxSendMsgSize(4 * 1024 * 1024),    // 4MB
        grpc.InitialWindowSize(1<<31 - 1),        // Flow control
        grpc.InitialConnWindowSize(1<<31 - 1),
    )
    pb.RegisterOrderServiceServer(s, &orderServer{})
    log.Fatal(s.Serve(lis))
}
Enter fullscreen mode Exit fullscreen mode

Client in Python:

import grpc
import order_pb2
import order_pb2_grpc

async def process_orders():
    async with grpc.aio.insecure_channel('localhost:50051') as channel:
        stub = order_pb2_grpc.OrderServiceStub(channel)

        async def generate_actions():
            for i in range(100):
                yield order_pb2.OrderAction(
                    order_id=f"ord-{i}",
                    action="process",
                    payload=b"{}",
                )

        async for result in stub.ProcessOrders(generate_actions()):
            print(f"Order {result.order_id}: {result.status}")
Enter fullscreen mode Exit fullscreen mode

WebSocket: Message-Based Protocol

WebSocket provides a simpler, message-oriented protocol over TCP:

// WebSocket client (browser)
const ws = new WebSocket('wss://api.example.com/orders');

// Connection lifecycle
ws.onopen = () => {
    console.log('Connected to order service');
    ws.send(JSON.stringify({
        type: 'subscribe',
        channels: ['orders.created', 'orders.status'],
    }));
};

ws.onmessage = (event) => {
    const message = JSON.parse(event.data);
    switch (message.type) {
        case 'order.created':
            displayNewOrder(message.data);
            break;
        case 'order.status':
            updateOrderStatus(message.data);
            break;
        case 'error':
            handleError(message.error);
            break;
    }
};

ws.onclose = (event) => {
    if (event.code !== 1000) {
        // Unexpected close, reconnect with exponential backoff
        scheduleReconnect(event.code);
    }
};

ws.onerror = (error) => {
    console.error('WebSocket error:', error);
};

// Send action
function processOrder(orderId) {
    if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
            type: 'process_order',
            order_id: orderId,
            timestamp: Date.now(),
        }));
    }
}
Enter fullscreen mode Exit fullscreen mode

Server in Node.js:


javascript
import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({
    port: 8080,
    maxPayload: 1024 * 1024,  // 1MB


---

**Read the full article on [AI Study Room](https://dingjiu1989-hue.github.io/en/compare/grpc-vs-websocket.html)** for complete code examples, comparison tables, and related resources.

*Found this useful? Check out more [developer guides and tool comparisons](https://dingjiu1989-hue.github.io/en/) on AI Study Room.*
Enter fullscreen mode Exit fullscreen mode

Top comments (0)