gRPC Service Types — Unary, Server Streaming, Client Streaming, Bidirectional
Fast recall
Quick revision
Core answer
.proto file using the stream keyword.Whether you know the four RPC shapes (unary, server-streaming, client-streaming, bidirectional), can map each to a real use case, and can write both the `.proto` declaration and the Java `StreamObserver` wiring for any of them.
Using unary for everything and polling for updates, when server-streaming is the natural fit. Or writing a bidirectional RPC and never calling `onCompleted()` on the server side, leaving the client's stream open forever.
Discuss cancellation via `Context.current().isCancelled()`, back-pressure in client-streaming, flow control via `CallStreamObserver.setOnReadyHandler`, and when gRPC bidirectional streaming displaces WebSocket for service-to-service real-time.
Interview-ready guide
Interview answer
gRPC gives you four RPC patterns built on HTTP/2 streaming, and the stream keyword in the .proto file controls which one you get. Each pattern suits different communication needs.
Unary — the default for most calls:
- One request, one response — exactly like REST; use it for 90% of service calls including lookups, CRUD operations, and anything request-response
- The simplest lifecycle: call the method, get a result, done; no streaming complexity or cancellation management required
Server streaming — replacing polling:
- The client sends one request and the server pushes a stream of responses — live order tracking, log tailing, streaming large query results
- Instead of clients polling every 2 seconds with full request overhead each time, the server pushes updates on a single connection at any rate; the single connection eliminates repeated TLS and HTTP setup costs
Client streaming:
- The client sends a sequence of messages and gets one response at the end; natural for chunked file uploads and telemetry batching where you send many small pieces and get a summary confirmation
Bidirectional streaming:
- Both sides push independently over a full-duplex channel; chat applications, collaborative editing, and trading feeds with acknowledgments all use this pattern
- The most complex lifecycle: both sides can send or close at any time, so error handling and cancellation require careful design
Lifecycle safety rules:
onErrorandonCompletedare both terminal onStreamObserver— call either twice and you getIllegalStateException- Always check
Context.current().isCancelled()in server-streaming loops or you'll keep producing data for disconnected clients
I recommend starting with unary and only adding streaming when polling overhead or per-call latency is a measured problem, not a theoretical one — streaming adds real lifecycle complexity.
gRPC Service Types — Unary, Server Streaming, Client Streaming, Bidirectional
Direct Answer
gRPC supports four RPC patterns: unary (one request, one response — like a normal function call), server streaming (one request, stream of responses — e.g. live updates), client streaming (stream of requests, one response — e.g. file upload), and bidirectional streaming (both sides stream concurrently — e.g. chat or real-time trading feeds). All four are expressed in the .proto file using the stream keyword.
Common Mistakes & Pitfalls
Using unary for everything and polling for updates, when server-streaming is the natural fit. Or writing a bidirectional RPC and never calling onCompleted() on the server side, leaving the client's stream open forever.
Check your understanding
Answer these without looking back at the article.
- How do you handle backpressure in a server-streaming gRPC call in Java?
- What happens to an open streaming RPC when the server restarts?
- Can you convert a bidirectional streaming RPC to use reactive streams (Project Reactor or RxJava)?
Related interview prep categories
1Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.