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
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;
}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
1. In a client streaming RPC, what does the server send back?
2. How does a client signal it has finished sending messages in a client streaming RPC?
3. Where does the 'stream' keyword appear in a client streaming RPC's proto definition?
4. Why must deadlines for client streaming RPCs be sized generously?
Was this page helpful?
You May Also Like
Unary RPC Explained
The simplest gRPC call pattern: one request in, one response out, modeled as a single HTTP/2 stream that opens and closes in a single round trip.
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.
Bidirectional Streaming RPC
A gRPC pattern where client and server each send an independent, ordered stream of messages over the same connection at the same time.
Choosing the Right RPC Type
A practical decision guide for picking between unary, server-streaming, client-streaming, and bidirectional-streaming gRPC methods.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics
Web DevelopmentNext.js Study Notes
JavaScript · 30 topics