Protocols Deep Dive: gRPC & WebSocket
Session 1.4 · ~5 min read
Beyond REST: Why Other Protocols Exist
Session 1.3 covered REST and GraphQL, both of which operate over HTTP/1.1 or HTTP/2 using text-based formats like JSON. They work well for many scenarios, but they carry overhead that becomes painful at scale or under specific constraints. Two protocols address these gaps directly: gRPC for high-performance service-to-service communication, and WebSocket for persistent, bidirectional real-time connections.
Understanding when to reach for each one is a core system design skill. The wrong protocol choice can introduce unnecessary latency, complexity, or resource consumption that compounds as the system grows.
gRPC: Binary, Typed, and Fast
gRPC is an open-source remote procedure call framework originally developed at Google. It uses HTTP/2 as its transport layer and Protocol Buffers (protobuf) as its serialization format. Both choices are deliberate.
Protocol Buffers are a language-neutral, platform-neutral mechanism for serializing structured data. You define your data schema in a .proto file, and the protobuf compiler generates strongly typed code in your target language. The binary encoding is significantly smaller and faster to parse than JSON.
HTTP/2 brings multiplexing (multiple requests over a single TCP connection), header compression, and server push. gRPC exploits all of these. A single connection between two services can carry hundreds of concurrent RPCs without the head-of-line blocking that plagues HTTP/1.1.
The Four gRPC Communication Patterns
gRPC supports four interaction modes, each suited to different scenarios:
| Pattern | Description | Use Case |
|---|---|---|
| Unary | Client sends one request, server sends one response | Standard API call (fetch user profile) |
| Server streaming | Client sends one request, server sends a stream of responses | Downloading large datasets, log tailing |
| Client streaming | Client sends a stream of messages, server sends one response | Uploading telemetry data in batches |
| Bidirectional streaming | Both sides send streams of messages independently | Real-time collaboration between services |
The strongly typed contract means both sides agree on the exact shape of every message at compile time. No runtime surprises from a missing field or a string where you expected an integer. This is a significant advantage in large systems where dozens of teams own different services.
WebSocket: Persistent and Bidirectional
WebSocket, standardized as RFC 6455 in 2011, solves a different problem. HTTP is inherently request-response: the client asks, the server answers, the connection is done. For applications that need the server to push data to the client without being asked, HTTP requires workarounds like long polling or server-sent events.
WebSocket replaces this with a persistent, full-duplex connection. The connection starts as a standard HTTP request with an Upgrade header. If the server agrees, the protocol switches from HTTP to WebSocket, and both sides can send messages at any time over the same TCP connection.
WebSocket provides full-duplex communication channels over a single TCP connection. After an initial HTTP handshake, the connection stays open. Either side can send messages at any time, with minimal framing overhead (as little as 2 bytes per frame).
The low per-message overhead makes WebSocket ideal for high-frequency, small-payload scenarios: chat messages, live price updates, multiplayer game state, collaborative editing cursors.
How They Differ in Practice
The gRPC call is request-response, even though the underlying HTTP/2 connection persists. Each RPC is a discrete unit with a defined start and end. WebSocket, by contrast, opens a channel that stays alive. Messages flow in both directions without the request-response framing.
Protocol Comparison Table
The following table compares gRPC, WebSocket, and REST across key dimensions relevant to system design decisions.
| Dimension | REST (HTTP/JSON) | gRPC | WebSocket |
|---|---|---|---|
| Transport | HTTP/1.1 or HTTP/2 | HTTP/2 (required) | TCP (after HTTP upgrade) |
| Data format | JSON (text) | Protocol Buffers (binary) | Any (text or binary frames) |
| Type safety | None (runtime validation) | Strong (compile-time from .proto) | None (application-defined) |
| Communication | Request-response | Unary + 3 streaming modes | Full-duplex, persistent |
| Browser support | Native | Requires gRPC-Web proxy | Native (all modern browsers) |
| Payload size | Larger (verbose JSON) | Smallest (binary encoding) | Depends on application |
| Best for | Public APIs, CRUD, web frontends | Internal service-to-service | Real-time client-server push |
| Tooling | Curl, Postman, any HTTP client | grpcurl, generated clients | Browser DevTools, wscat |
Where Each Protocol Fits
gRPC dominates internal service communication in large distributed systems. When Service A calls Service B 10,000 times per second, the difference between JSON parsing and protobuf deserialization is measurable. The strict contract prevents the subtle breaking changes that plague loosely typed JSON APIs across team boundaries. Companies like Google, Netflix, and Stripe use gRPC extensively for backend-to-backend traffic.
WebSocket dominates scenarios where the server needs to push data to clients without waiting for a request. Chat applications, live dashboards, multiplayer games, collaborative editors. Any feature where a user expects to see updates the moment they happen, without refreshing.
REST remains the default for public-facing APIs, CRUD operations, and any scenario where simplicity, cacheability, and broad client compatibility matter more than raw performance.
Systems Thinking Lens
Protocol choice is a leverage point in the system. Choosing gRPC for internal communication reduces serialization overhead across every service boundary. That reduction compounds: fewer CPU cycles per request means fewer instances needed, which means lower cost, which means more budget for features. The feedback loop runs through infrastructure cost, team velocity, and product capability.
Conversely, choosing WebSocket where simple polling would suffice introduces connection management complexity, memory overhead for open connections, and operational burden for connection state during deploys. The protocol that feels more "advanced" can make the overall system worse if the problem did not require it.
The right question is never "which protocol is best?" It is "what does this specific interaction need, and what are the second-order effects of this choice on the rest of the system?"
Further Reading
- Introduction to gRPC (grpc.io). Official overview of gRPC concepts, HTTP/2 transport, and Protocol Buffers integration.
- Core concepts, architecture and lifecycle (grpc.io). Detailed explanation of the four gRPC communication patterns and connection lifecycle.
- RFC 6455: The WebSocket Protocol (IETF). The formal specification for WebSocket, including the handshake, framing, and closing procedures.
- WebSocket API (MDN Web Docs). Practical guide to using WebSocket in browser-based applications.
- Protocol Buffers Overview (protobuf.dev). Official documentation for defining and using Protocol Buffer schemas.
Assignment
Match each use case below to the most appropriate protocol (REST, gRPC, or WebSocket). Write one or two sentences justifying each choice.
- Live chat application where users see messages instantly as they arrive.
- Microservice-to-microservice communication in a payment processing pipeline handling 50,000 transactions per second.
- Stock ticker dashboard displaying real-time price updates for 200 symbols.
- Mobile app API for a food delivery service where users browse restaurants, place orders, and track delivery.
For each answer, consider: What is the communication pattern? Who initiates data flow? How critical is latency? Does the client need a persistent connection, or is request-response sufficient?