100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Protocol Buffers

Server Streaming RPC

A gRPC pattern where the client sends one request and the server replies with a sequence of messages over time on the same stream.

Service TypesIntermediate9 min readJul 10, 2026
Analogies

What Is a Server Streaming RPC?

In server streaming, the client sends a single request message, and the server responds not with one message but with a sequence of messages sent over time on the same HTTP/2 stream, terminated by a status trailer once the server has nothing more to send. The client reads messages from an iterator or callback as they arrive rather than waiting for one complete payload, which lets the server start producing results before the entire result set is ready. This is the natural fit for things like paginated result sets streamed as they're computed, log tailing, or price-update feeds.

🏏

Cricket analogy: It is like subscribing to ball-by-ball commentary after asking 'start covering this match': one request, and then a continuous stream of updates — dot ball, four, wicket — arrives until the innings ends.

Backpressure and Flow Control

Because HTTP/2 streams have flow control built in at both the stream and connection level, a server streaming RPC naturally applies backpressure: if the client is slow to read, its receive window shrinks and the server's writes eventually block until the client catches up, preventing unbounded memory growth on either side. Application code should still avoid holding an expensive resource, such as a database cursor, open for the entire duration of a slow-consuming client, and should watch for context cancellation in case the client disconnects mid-stream.

🏏

Cricket analogy: It is like a stadium's PA announcer pacing ball updates to how fast the scoreboard operator can key them in — if the operator falls behind, the announcer must wait rather than flooding the board.

Defining and Implementing a Server Streaming RPC

protobuf
syntax = "proto3";

service StockService {
  // Server streaming: one request, a stream of responses.
  rpc WatchPrice(WatchPriceRequest) returns (stream PriceUpdate);
}

message WatchPriceRequest {
  string symbol = 1;
}

message PriceUpdate {
  string symbol = 1;
  double price = 2;
  int64 timestamp_ms = 3;
}
go
func (s *stockServer) WatchPrice(req *pb.WatchPriceRequest, stream pb.StockService_WatchPriceServer) error {
    ticker := time.NewTicker(500 * time.Millisecond)
    defer ticker.Stop()

    for {
        select {
        case <-stream.Context().Done():
            // Client disconnected or deadline exceeded; stop producing.
            return stream.Context().Err()
        case <-ticker.C:
            price := s.priceFeed.Latest(req.Symbol)
            if err := stream.Send(&pb.PriceUpdate{
                Symbol:      req.Symbol,
                Price:       price,
                TimestampMs: time.Now().UnixMilli(),
            }); err != nil {
                return err
            }
        }
    }
}

A server streaming RPC has no upper bound by default, so a poorly bounded stream can run forever and leak goroutines or threads. Always watch stream.Context().Done() (or the equivalent in your language) so you release resources promptly when the client cancels or disconnects.

Common Use Cases

Server streaming shines whenever a single logical request naturally produces a sequence of results over time: exporting a large table in chunks instead of one giant response, tailing application logs, streaming search results as they're ranked, or pushing live notifications after a client subscribes to a topic. It is also useful for large one-time downloads, since chunking a large file into a stream of byte-range messages avoids allocating one enormous in-memory response and lets the client start processing the first chunk before the rest arrives.

🏏

Cricket analogy: It resembles a stadium's video review system streaming replay angles one after another to the third umpire's screen instead of sending a single giant combined video file.

Server streaming responses still share the retry semantics of the underlying call for the initial request, but once messages have started flowing, most gRPC clients will not automatically retry a broken stream — application code typically needs to reconnect and resubscribe from a known offset or checkpoint.

  • Server streaming sends one client request but returns a sequence of server messages over one HTTP/2 stream.
  • HTTP/2 flow control provides natural backpressure between a fast server and a slow-reading client.
  • Handlers must watch for context cancellation to stop producing once a client disconnects.
  • The stream is proto-declared with the 'stream' keyword on the response type only.
  • Good fits include log tailing, price feeds, paginated exports, and chunked large-file downloads.
  • Streams do not auto-retry once started; reconnect-and-resume logic is the application's responsibility.
  • Avoid holding expensive resources like DB cursors open for the full duration of a slow client.

Practice what you learned

Was this page helpful?

Topics covered

#ProtocolBuffers#GRPCStudyNotes#WebDevelopment#ServerStreamingRPC#Server#Streaming#RPC#Backpressure#StudyNotes#SkillVeris