The 30 second answer
gRPC is a remote procedure call framework. You declare messages and services in a proto file, generate stubs, and call methods instead of hand-writing URLs. The default stack is HTTP/2 for transport and Protocol Buffers for the contract. There are four method kinds: unary, server streaming, client streaming and bidirectional streaming. I always set a deadline, because there is no default, and I treat the result as a gRPC status, not as an HTTP status.
gRPC is a remote procedure call framework. A service is defined as a set of named methods, each with a request and response type. The default stack is HTTP/2 for transport and Protocol Buffers (protobuf) for the contract and payload. Other encodings exist, but protobuf is the one the official documentation assumes.
HTTP/2 multiplexes many concurrent streams over one connection, with binary framing and header compression. gRPC maps each RPC to an HTTP/2 stream. That is why a single long-lived connection can carry many in-flight calls, and why connection-level load balancing is a common operational pitfall, covered in the next question.
You declare messages and services in a .proto file and run protoc, with a gRPC plugin, to generate stubs and skeletons. Field numbers identify fields on the wire; they are not decorative and must not be changed once a type is in use. In Java this is commonly wired through a gRPC server or a Spring Boot application that hosts generated services. Callers typically call a generated method rather than hand-writing URL paths or JSON field names.
gRPC defines four kinds of method. Message order is preserved within an individual RPC.
- Unary. The client sends one request and receives one response:
rpc SayHello(HelloRequest) returns (HelloResponse); - Server streaming. The client sends one request and reads a sequence of responses until the stream ends:
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse); - Client streaming. The client writes a sequence of messages, then waits for a single response:
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse); - Bidirectional streaming. Both sides send a sequence of messages on a read-write stream. The two streams are independent: the server may wait for all client messages, or interleave reads and writes.
syntax = "proto3";
package catalog.v1;
service Catalog {
rpc GetOffer(GetOfferRequest) returns (Offer);
rpc WatchPrices(WatchPricesRequest) returns (stream PriceTick);
}
message GetOfferRequest {
string offer_id = 1;
}
message Offer {
string id = 1;
string title = 2;
Money price = 3;
}
message Money {
string currency_code = 1;
string decimal_amount = 2;
}
message WatchPricesRequest {
repeated string offer_id = 1;
}
message PriceTick {
string offer_id = 1;
Money price = 2;
}Deadlines and cancellation. Clients should set a deadline (a point in time) or a timeout (a duration, converted to a deadline when the call starts). If the deadline passes, the client fails the RPC with DEADLINE_EXCEEDED. By default gRPC does not set a deadline, so a client can wait indefinitely; official guidance is to always set a realistic one. On the server, once the client's deadline has passed, gRPC cancels the call (CANCELLED). The application is still responsible for stopping work it spawned. When a server makes a downstream RPC, some implementations, including Java and Go by default, propagate the remaining deadline. Either side may cancel an RPC at any time.
Every RPC returns a status: an integer code plus a description. These are not HTTP status codes. Applications should use only the defined codes. A unary success is a generated message with status OK (0). A missing offer is NOT_FOUND (5), not an HTTP 404 at the application layer. Other codes interviewers expect include INVALID_ARGUMENT (3), DEADLINE_EXCEEDED (4), PERMISSION_DENIED (7), UNAVAILABLE (14) and UNAUTHENTICATED (16). UNAVAILABLE is the usual signal that a retry with backoff may be appropriate; it is not always safe to retry a non-idempotent RPC.
Alternate interview scenarios
"Walk me through a streaming search API."
I would use server streaming: the client sends one query and reads hits as they become available, which avoids waiting to buffer the whole page. If both sides need to talk at once, for example a session that refines the query while results still arrive, I would use bidirectional streaming. I would still set a deadline on the call, and I would be ready to cancel if the user walks away.
"What happens if you forget to set a timeout on a gRPC call?"
There is no default deadline, so the client can wait indefinitely. I treat that the same way I treat a missing HTTP client timeout: it is a production defect. I set a realistic deadline and make sure the server stops work when the call is cancelled.
Sources (4)
- gRPC core conceptsgrpc.io
- Protocol Buffers proto3 language guideprotobuf.dev
- gRPC deadlinesgrpc.io
- gRPC status codesgrpc.io