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

Client Streaming RPC

A gRPC pattern where the client sends a sequence of messages over one stream and the server replies with a single response once the client finishes.

Service TypesIntermediate9 min readJul 10, 2026
Analogies

What Is a Client Streaming RPC?

Client streaming reverses the direction of server streaming: the client sends a sequence of messages over a single HTTP/2 stream, and the server reads them as they arrive but sends back only one response message, typically after the client signals it is done by half-closing the stream. This is the natural fit for uploads, batch ingestion, and any workload where a client wants to push a series of items and receive a single acknowledgment or aggregate result, such as a summary count or computed total, once the whole sequence has been processed.

🏏

Cricket analogy: It is like a fielding coach recording every ball of a bowler's entire net session on a tablet and only submitting one final performance report once the session ends.

Half-Closing the Stream

The client signals it has no more messages to send by calling a method such as CloseAndRecv (Go, Python's done sending), which half-closes its side of the HTTP/2 stream while leaving it open to receive the server's single response. The server, meanwhile, is free to start processing incoming messages incrementally as they arrive rather than buffering the entire sequence, which is important for large uploads where holding everything in memory until the end would be wasteful or infeasible.

🏏

Cricket analogy: It is like a batter signalling 'declare' at the end of an innings — no more runs will be added, but the team still waits to hear the final scorecard verdict from the scorers.

Defining and Implementing a Client Streaming RPC

protobuf
syntax = "proto3";

service TelemetryService {
  // Client streaming: a stream of requests, one response.
  rpc UploadMetrics(stream MetricPoint) returns (UploadSummary);
}

message MetricPoint {
  string name = 1;
  double value = 2;
  int64 timestamp_ms = 3;
}

message UploadSummary {
  int32 points_received = 1;
  bool accepted = 2;
}
python
def generate_points(readings):
    for r in readings:
        yield telemetry_pb2.MetricPoint(
            name=r.name, value=r.value, timestamp_ms=r.ts_ms
        )

stub = telemetry_pb2_grpc.TelemetryServiceStub(channel)
summary = stub.UploadMetrics(generate_points(sensor_readings), timeout=10.0)
print(f"Server accepted {summary.points_received} points: {summary.accepted}")

Because the server response only arrives after the client finishes sending, a client streaming RPC's deadline must cover the entire upload duration, not just a single message. A deadline sized for one message will cause large uploads to fail with DEADLINE_EXCEEDED partway through.

When Client Streaming Fits Best

Client streaming is ideal when a client naturally produces items incrementally — sensor readings from an IoT device, log lines from a batch job, or chunks of a file being uploaded — and only needs a single acknowledgment, aggregate, or validation result at the end. It avoids the overhead of issuing thousands of separate unary calls for each item, while letting the server process and validate data incrementally rather than requiring the client to first assemble a single giant request message in memory.

🏏

Cricket analogy: It resembles a groundstaff crew feeding pitch-moisture sensor readings continuously throughout the day into a single monitoring session, with the curator only needing one final 'pitch ready' verdict before play.

If you also need the server to react to each item as it arrives — not just acknowledge the whole batch at the end — client streaming is the wrong tool; use bidirectional streaming instead so the server can send interleaved responses.

  • Client streaming sends many client messages over one stream but returns a single server response.
  • The client half-closes its side of the stream (e.g. CloseAndRecv) to signal it is finished sending.
  • Servers can process incoming messages incrementally instead of buffering the entire sequence.
  • The proto definition marks only the request type with the 'stream' keyword.
  • Deadlines must be sized for the whole upload duration, not a single message.
  • Good fits include IoT telemetry ingestion, batch uploads, and file-chunk uploads with one final ack.
  • Use bidirectional streaming instead if the server must react per-item rather than only at the end.

Practice what you learned

Was this page helpful?

Topics covered

#ProtocolBuffers#GRPCStudyNotes#WebDevelopment#ClientStreamingRPC#Client#Streaming#RPC#Half#StudyNotes#SkillVeris