Lesson 5 · Streaming RPCs
Server streaming
One request in, a stream of responses out — how live chat rides gRPC.
Your win: explain server streaming, read its Go handler shape
(Send in a loop, no ctx arg), and say when to reach for it —
anchored to tom's real-time chat Subscribe.
The shape: 1 request → many responses
The client sends a single request; the server sends back a stream of
messages, one at a time, until it closes the stream. The client reads them as they
arrive.1 The stream keyword goes on
the response:
rpc Subscribe(SubscribeRequest) returns (stream SubscribeResponse);
The Go handler looks different from unary
No context.Context parameter and no return-value response — instead you
get a stream object and push messages through it:
func (rcv *Server) SubscribeV2(req *pb.SubscribeV2Request,
srv pb.ChatService_SubscribeV2Server) error {
userID := interceptors.UserIDFromContext(srv.Context()) // ctx via srv.Context()
...
return clientConn.PumpSubscribeV2() // loops, calling srv.Send(event) per event
}
ctx param
— get it from srv.Context(). (2) You don't return a response
— you call srv.Send(msg), usually in a loop. (3) You return
error (or nil) to end the stream.
When to use it
Server streaming shines when one request yields many or open-ended results: a live feed, server-push notifications, progress updates, or a large result set you'd rather stream than buffer.
tom is the live chat service; a client calls Subscribe once
and tom pushes every new chat event down the stream over a single HTTP/2
connection. Your own three services (conversationmgmt/notification/spike) are unary —
tom is the streaming counterpart. That split is itself a design choice:
chat delivery streams; chat management is unary CRUD.
gRPC — Core concepts (Server streaming) + Go Basics tutorial
Core concepts defines the lifecycle; the Go Basics tutorial has you implement a
server-streaming method with stream.Send.
Check yourself (from memory)
Q1. In server streaming, the stream keyword is on the…
stream marks the response: returns (stream Resp).
Q2. A server-streaming Go handler sends messages via…
srv.Send(msg)
and return nil/err to end. No response is returned.
Q3. Server streaming is a good fit for…
Subscribe.
stream on the response), read until the server closes. Go handler:
func(req *Req, srv X_Server) error — no ctx arg (use
srv.Context()), no returned response; call srv.Send(msg) in a
loop and return nil/err to end. Repo example: tom's
Subscribe (chat_modifier.proto:171 → api.go:19), pushing live chat events.
Good for feeds, progress, large result sets.for { resp, err := stream.Recv() })?
Ask me.