The Four Streaming Modes
🔀 The Four Streaming Modes
Unary — Recap
One request in, one response out. The baseline every other mode is described relative to.
Server Streaming
One request, many responses streamed back over time. The stream keyword on the response type marks it.
Right for live updates — subscribing to stock price changes, streaming search results as they're found, watching a long-running job's progress. One request establishes the subscription; the server pushes as many responses as it needs to, whenever it has something new.
Client Streaming
Many requests streamed from the client, one response at the end. The stream keyword moves to the request type instead.
Right for batch uploads — sending a large file in chunks, or submitting many sensor readings and getting back a single confirmation/summary once all of them have arrived, rather than paying the overhead of a separate unary call per chunk.
Bidirectional Streaming
Both sides stream independently and simultaneously — neither side waits for the other to finish before sending more.
Right for genuinely chat-like exchanges — a live chat, real-time collaborative editing — the closest gRPC gets to the full-duplex model web-sockets1-2 defined for raw WebSockets.
| Mode | Syntax Shape | Use Case |
|---|---|---|
| Unary | rpc M(Req) returns (Res); | A single request/response — the default choice |
| Server streaming | rpc M(Req) returns (stream Res); | Live updates, subscriptions |
| Client streaming | rpc M(stream Req) returns (Res); | Batch uploads, chunked submission |
| Bidirectional streaming | rpc M(stream Req) returns (stream Res); | Chat, real-time collaboration |
Implementing Server Streaming
Unlike a unary handler's single callback, a server-streaming handler calls write() as many times as it needs to, and must explicitly handle the client disconnecting mid-stream — a lifecycle unary calls never have to think about.
gRPC Bidi Streaming vs. Raw WebSockets
Both are full-duplex, but gRPC's bidirectional streams are still schema-constrained by Protobuf messages and shaped around an RPC method — raw WebSockets (the WebSockets course) are a free-form byte/message channel with no inherent request/response or schema structure at all.
When to Reach for Which
gRPC bidi streaming fits when both ends are internal services that benefit from a typed schema; raw WebSockets fit better when a browser is one of the endpoints, or when the message shape needs to stay flexible.
💻 Coding Challenges
Challenge 1: Pick the Right Streaming Mode
For each, name the correct mode and write its rpc signature: (a) a client uploading a large log file in 1MB chunks, getting one confirmation back, (b) a dashboard subscribing to live order-count updates.
Goal: Practice matching a use case to the correct streaming direction and syntax.
Challenge 2: Explain Why Unary Doesn't Fit
Explain why implementing a live stock-price subscription as a unary call (the client polling repeatedly) is a worse fit than server streaming, in terms of both efficiency and design.
Goal: Practice articulating what server streaming specifically buys over repeated unary polling.
Challenge 3: gRPC Bidi or WebSockets?
A team is building a real-time multiplayer game where the browser is one of the two endpoints. Should they use gRPC bidirectional streaming or raw WebSockets? Justify your answer.
Goal: Practice applying this chapter's gRPC-vs-WebSockets distinction to a concrete architectural decision.
A streaming handler has to manage a genuine lifecycle a unary call never does: knowing when the stream should end, handling a client disconnecting mid-stream, and dealing with errors that occur partway through rather than all-or-nothing. This complexity is worth paying when a use case genuinely needs ongoing or many-part communication — but it's a real cost, not a free upgrade. Unary should be the default for any call that's fundamentally "ask a question, get an answer"; reach for one of the three streaming modes only when the shape of the actual problem — live updates, chunked uploads, a genuinely two-way exchange — calls for it.
🎯 What's Next
The next chapter is Error Handling & Metadata — gRPC status codes vs. HTTP status codes, rich error details, metadata (gRPC's header equivalent), and deadlines/timeouts.