skip to content

gRPC

A contract-first framework where a schema generates both ends of a call and every request rides one long-lived HTTP/2 connection. Interviewers use it as the internal-service counterpart to REST.

part ofAPI stylesoverview, primer and where to startread it →
on this pageshow

questions

page 1 of 2

What are the four gRPC method kinds, and which one fits a device that uploads a sample every few seconds for hours?

level: juniorimportance: must knowfreq 85%

answer

  1. two sides, one or many each
  2. two binary choices, four shapes
  3. one request, many responses
  4. many requests, one response
  5. sequence in both directions

basics

~10 s

gRPC methods come in four kinds: unary (one request, one response), server-streaming (one request, many responses), client-streaming (many requests, one response) and bidirectional streaming. A device uploading samples for hours fits client-streaming.

solid answer

~40 s

Every gRPC method is exactly one of four kinds, decided by whether each side sends a single message or a sequence. **Unary** is one request and one response. **Server-streaming** is one request and a sequence of responses. **Client-streaming** is a sequence of requests and a single response. **Bidirectional streaming** is a sequence in each direction. The generated method signature follows: a streaming direction shows up as a sequence you write into or read from rather than a single value. A harvester pushing a yield sample every few seconds for six hours and wanting one summary at the end is client-streaming — and all of it is *one call*, with one status at the end, not thousands of calls.

code

pseudocode · 13 lines
pseudocode
// the four generated method shapes, one per method kind

registerMachine(request: Machine) returns Receipt
// unary: one message each way

readYieldMap(request: FieldQuery) returns sequence of MapTile
// server-streaming: one request, many responses

uploadRun(requests: sequence of Sample) returns RunSummary
// client-streaming: many requests, one response

liveRun(requests: sequence of Sample) returns sequence of Correction
// bidirectional: a sequence in each direction

go deeper

for a junior

Be able to name all four kinds and say which side streams in each. Then pick one for a described data flow and justify it in a sentence — that is the whole question at this level.

for a middle

Explain that a streaming call is one call with one outcome at the end, and that the generated signature turns a streaming direction into a sequence you write into or read from rather than a single value.

for a senior

Show that you choose the kind from the shape of the data flow, and that you know what a long-lived call costs: a handler occupied for hours, and a call that dies with the server instance holding it.

for a principal

The angle here is where a long call belongs in a system's failure budget at all: a trickle of short calls and one call held open for six hours fail in different ways, and only one of them survives a routine restart.

gRPC methods come in exactly four kinds. The kind is decided by one question asked twice: does the client send a single message or a sequence, and does the server answer with a single message or a sequence? Two binary choices give four shapes, and every method a service declares is exactly one of them. The kind is fixed at declaration time — a caller cannot turn a unary method into a streaming one at the call site. ## The four kinds - **Unary** — the client sends one message, the server answers with one message. This is the shape that reads like an ordinary function call, and it is still the most common one in practice. - **Server-streaming** — the client sends one message, the server answers with a sequence of messages of any length, then ends the call. - **Client-streaming** — the client sends a sequence of messages, the server answers with a single message once that sequence is finished. - **Bidirectional streaming** — both sides send sequences, and neither sequence has to wait on the other. | Kind | Client sends | Server sends | What the generated method gives the caller | |---|---|---|---| | Unary | one message | one message | a request argument, one response value | | Server-streaming | one message | many messages | a request argument, a readable sequence | | Client-streaming | many messages | one message | a writable sequence, one response value | | Bidirectional | many messages | many messages | a writable sequence and a readable sequence | The last column is the practical difference at the call site. A streaming direction is not a bigger message; it is a sequence you write into or read from over time, and the generated signature says so. ## A streaming call is one call The most common misreading is that a streaming method is a convenience wrapper over many calls. It is not. Everything in a streaming call happens inside a **single call**: one call beginning, one sequence of messages in each streaming direction, and exactly **one status at the end** that reports the outcome of the whole thing. Five thousand yield samples uploaded on a client-streaming method are five thousand messages inside one call — not five thousand calls. Two consequences follow immediately: 1. A failure partway through does not fail "one of the messages". It fails the call, and every message already sent belongs to a call that ended badly. 2. The protocol defines **no per-message acknowledgement**. If the application wants one, it has to be a message travelling in the other direction — which means the method kind must *have* another direction, and that is bidirectional streaming. ## Picking a kind for the harvester - The machine samples yield every few metres for six hours and the back office replies once, at the end, with a run summary → **client-streaming**. - The machine sends samples *and* wants calibration corrections back while it is still cutting → **bidirectional streaming**. - The office asks for a finished field's yield map and the server produces it row by row → **server-streaming**. - The machine registers itself, or reports that a run has started → **unary**. Notice that the choice is driven by the *shape of the data flow*, not by how much data there is. A large payload that is ready all at once can still be a unary response; a small trickle produced over hours cannot honestly be one. ## Why not call a unary method in a loop A loop of unary calls is a legitimate design and sometimes the right one, but it is a different design, not the same one written differently. Each iteration is an independent call with its own beginning, its own outcome and its own per-call overhead, and nothing ties the sequence together — the server sees unrelated calls and has to correlate them itself from something in the messages. A single streaming call gives the server one handler invocation that sees the whole sequence in order, and gives the client one outcome to handle instead of thousands. ## What a streaming kind costs - The call is long-lived, so it occupies a server-side handler for its entire life rather than for a few milliseconds. - It ends when that server instance goes away — a restart ends every call in flight, where a loop of short calls simply continues against whatever instance answers next. - One deadline covers the whole call, so the bound has to be sized for the *whole* sequence and not for one message. Naming the four kinds is a first-screen question. Knowing that a stream is one call with one outcome is what the interviewer is actually listening for.

  • Is a server-streaming gRPC call many calls or one?
    One. The whole sequence of response messages lives inside a single call: one beginning, many messages, and exactly one status at the end that reports the outcome of the entire call. The messages are not individually acknowledged and they do not have individual outcomes — if the call fails halfway through, it is the call that failed.
  • The harvester must also receive calibration corrections while it is still uploading samples. Which kind now?
    Bidirectional streaming. Client-streaming gives the server exactly one message to send, and it can only send it once the client's sequence is finished, so corrections could not arrive mid-run. Bidirectional gives each side its own sequence, so the office can send a correction at any point while samples are still arriving.
  • Can the same service mix kinds?
    Yes — the kind is a property of each method, not of the service or the connection. A service can declare a unary registration method, a client-streaming upload and a bidirectional live session side by side, and calls of all three kinds run concurrently over the same connection.

Posting one letter and getting one back, subscribing to a newsletter, mailing a stack of forms and getting one receipt, or holding a correspondence where either side writes whenever it likes.

saying these in an interview costs you the question

  • Says gRPC only does request and response, like a plain HTTP API
  • Treats every streamed message as its own call with its own outcome
  • Picks server-streaming for a job where the client is the sender
  • Thinks a streaming method needs a new connection per message
  • Assumes the four kinds differ only in payload size
open as a page

A gRPC client makes a unary call and sets no deadline. What does the server assume, and why is that dangerous?

level: juniorimportance: must knowfreq 72%

basics

~20 s

With no deadline the call carries no grpc-timeout request field, and the gRPC specification tells the server to assume an infinite timeout. One stalled dependency then holds caller threads and memory until something else breaks.

open as a page

What does a gRPC call look like as an HTTP/2 request, and how does the server know which method is wanted?

level: juniorimportance: must knowfreq 62%

basics

~10 s

Every gRPC call is an HTTP/2 POST whose :path is /{package}.{Service}/{Method}, with content-type application/grpc and te: trailers. The request body carries length-prefixed messages; nothing about the call lives in a query string.

open as a page

In gRPC, what is an interceptor and where does it run relative to the service method it wraps?

level: juniorimportance: must knowfreq 60%

basics

~20 s

An interceptor is a wrapper around a gRPC call that runs before and after the service method, on the client side or the server side, so cross-cutting work like authentication, audit logging, timing and tracing lives in one place.

open as a page

Why does a caller ask a gRPC server's grpc.health.v1 Health service whether it is serving instead of trusting that the connection was accepted?

level: juniorimportance: must knowfreq 64%

basics

~20 s

Accepting a connection only proves a process bound its port. The grpc.health.v1 Health service's Check call returns a ServingStatus for a named service, so a caller learns whether the server can actually answer work rather than merely that it is listening.

open as a page

In gRPC, what does a service stanza in a .proto file declare, and what code does each side get from it?

level: juniorimportance: must knowfreq 72%

basics

~20 s

A service stanza names a gRPC service and lists its rpc methods, each with one request and one response message type. The generator turns that into a callable client stub and an abstract server base type the implementation extends.

open as a page

Why can a browser page not call a gRPC service directly, and what does gRPC-Web change so it can?

level: juniorimportance: must knowfreq 70%

basics

~20 s

gRPC-Web exists because browser code cannot control HTTP/2 framing or read trailing metadata. It carries a call as an ordinary HTTP request whose response body ends with the trailing status, and a translating layer converts to native gRPC.

open as a page

In a gRPC client-streaming call, what does half-close mean, and what may the server do afterwards?

level: middleimportance: must knowfreq 58%

basics

~20 s

Half-close means the sending side has finished its sequence of request messages while the call stays open. The server can keep reading what it buffered, then send its response and the single status that ends the call.

open as a page

A gRPC handler rejects a request. How do you choose between INVALID_ARGUMENT, FAILED_PRECONDITION, NOT_FOUND and UNIMPLEMENTED?

level: middleimportance: must knowfreq 64%

basics

~20 s

Ask what is wrong. The arguments themselves give INVALID_ARGUMENT (3); well-formed arguments blocked by system state give FAILED_PRECONDITION (9); a named entity that does not exist gives NOT_FOUND (5); a method this server does not implement gives UNIMPLEMENTED (12).

open as a page

How does a gRPC caller's deadline reach the server, and what does a grpc-timeout value actually look like?

level: middleimportance: must knowfreq 60%

basics

~10 s

It travels as one request metadata field, grpc-timeout, whose value is a positive integer of at most eight ASCII digits followed immediately by a single unit letter: H, M, S, m, u or n.

open as a page

A gRPC call fails, yet the HTTP :status on its response is 200 — where does the real outcome travel?

level: middleimportance: must knowfreq 74%

basics

~20 s

Once the server accepts a gRPC call, the response carries :status 200 whatever happens; the outcome rides in the trailing metadata as grpc-status, with grpc-message beside it. A call that fails immediately uses a Trailers-Only response.

open as a page

With three gRPC server-side interceptors composed into a chain, which one sees the request first and the status last?

level: middleimportance: must knowfreq 52%

basics

~20 s

The outermost one. A chain of gRPC interceptors nests around the service method, so pre-work runs outside in and post-work unwinds inside out: the outermost wrapper sees the request first and the call's status last.

open as a page

How does the Watch call in gRPC's grpc.health.v1 Health service differ from Check, and what does Watch give a caller?

level: middleimportance: must knowfreq 60%

basics

~20 s

Check is unary: one request, one response, the status now. Watch is server-streaming: the caller sends one request, the server answers with the current status immediately and sends a further message on every change for the life of the call.

open as a page

In gRPC, what does a pick_first policy do with the resolved address list, and how does round_robin differ?

level: middleimportance: must knowfreq 70%

basics

~20 s

pick_first connects to the resolved addresses in order and sends every call over the first connection that comes up. round_robin opens a subchannel to each address and rotates calls across the ready ones, so a pool actually shares work.

open as a page

Which gRPC call shapes can a browser client use over gRPC-Web, and which two does it lose?

level: middleimportance: must knowfreq 60%

basics

~20 s

A browser client over gRPC-Web gets unary and server-streaming calls. Client-streaming and bidirectional streaming are not available, because the variant is carried by an ordinary HTTP request whose body is complete before the response begins.

open as a page

One worker in a round_robin gRPC channel stops accepting connections — what happens to its subchannel and to the channel's own state?

level: seniorimportance: must knowfreq 55%

basics

~10 s

That worker's subchannel moves to TRANSIENT_FAILURE and the picker drops it from rotation until it reconnects and reports READY. The channel itself stays READY while at least one other subchannel is READY.

open as a page

Which edits to a shared gRPC service stanza are safe to ship, and which break the teams already compiling against it?

level: seniorimportance: must knowfreq 58%

basics

~20 s

Adding an rpc method is additive — callers that never regenerate are unaffected. Renaming or removing a method, or renaming the service or its proto package, breaks every caller compiled against the old name, because those names are the call's identity.

open as a page

In gRPC, what does the scheme at the front of a channel target string select, and which port applies when none is given?

level: juniorimportance: should knowfreq 45%

basics

~10 s

The scheme selects the name resolver: dns: resolves a name to addresses, ipv4: and ipv6: take literal addresses, unix: points at a local socket. A dns: target that names no port defaults to 443.

open as a page

In gRPC, what is the difference between channel credentials and call credentials, and why should call credentials only travel over a secured channel?

level: middleimportance: should knowfreq 44%

basics

~20 s

Channel credentials, such as TLS, secure the whole connection and are set when the channel is created. Call credentials add authentication metadata, like an access token, to each call: a plain header that anyone on the path can read and replay without TLS.

open as a page

What rules govern a custom gRPC metadata key and its value, and where on a call may it travel?

level: middleimportance: should knowfreq 52%

basics

~10 s

Keys are lowercase and drawn from digits, a-z, underscore, hyphen and dot; the grpc- prefix is reserved. Plain values are printable ASCII only, so binary needs a key ending -bin whose value is base64.

open as a page

Inside a gRPC call's DATA frames, what precedes each message, and why can't one frame be read as one message?

level: middleimportance: should knowfreq 48%

basics

~10 s

Each message carries a five-byte prefix: one Compressed-Flag byte, then a four-byte big-endian Message-Length. HTTP/2 DATA frame boundaries are unrelated to message boundaries, so a receiver reads by that declared length, never by frame.

open as a page

How does a gRPC interceptor wrapping a server-streaming method differ in shape from one wrapping a unary method?

level: middleimportance: should knowfreq 44%

basics

~20 s

A unary wrapper sees one request and one outcome, so it can work before the call, invoke it, and inspect what came back. A streaming wrapper has no single value: it must hook per-message callbacks and the terminal status of an open-ended sequence.

open as a page

Why is a NOT_FOUND status from a gRPC health Check not the same answer as a NOT_SERVING ServingStatus?

level: middleimportance: should knowfreq 44%

basics

~20 s

They answer different questions. NOT_SERVING is a value inside a successful HealthCheckResponse and means a registered service cannot take work. NOT_FOUND fails the call and means the server has nothing registered under the name that was sent.

open as a page

What can a caller look up through gRPC server reflection, and what does the server send back?

level: middleimportance: should knowfreq 50%

basics

~20 s

Server reflection answers descriptor lookups at runtime: a file by name, the file containing a symbol, the file containing an extension of a type, and the extension numbers known for a type. The server returns file descriptors, including the transitive imports of what was asked for.

open as a page

A gRPC caller invokes an rpc method the deployed server never implemented — what comes back, and why is it not a transport error?

level: middleimportance: should knowfreq 50%

basics

~20 s

The call reaches the server and comes back with gRPC status UNIMPLEMENTED (12). The connection was healthy and the server answered — it simply has no handler for the method named, which signals contract skew rather than a connectivity problem.

open as a page

In a gRPC-Web response body, how does a client tell the trailer frame from a message frame?

level: middleimportance: should knowfreq 52%

basics

~20 s

Every frame in a gRPC-Web response body opens with a flag byte and a four-byte length. gRPC-Web sets the most significant bit of that flag byte to mark the trailer frame: 0x80 uncompressed, 0x81 compressed. It must be the last frame.

open as a page

When a client cancels an in-flight gRPC streaming call mid-run, what does the server-side handler observe and have to do?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Cancelling aborts the whole call in both directions. The server's handler stops receiving messages and its reads and writes on that call start failing as cancelled; it must notice, stop working and release what the call held. No response is delivered.

open as a page

When should a gRPC method server-stream a large result set instead of returning it in paged unary calls?

level: seniorimportance: should knowfreq 52%

basics

~20 s

Stream when the results are produced over time, are large or unbounded, or the caller should see the first one before the last exists. Page with unary calls when the caller needs to resume from a known position or hold no long-lived call.

open as a page

Besides the numeric grpc-status, what may a failed gRPC call return to explain itself, and under what constraints?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Two optional companions, both in the call's trailing metadata: grpc-message, a percent-encoded human-readable string, and grpc-status-details-bin, a base64 payload holding a google.rpc.Status whose code must agree with grpc-status and which is only sent when the status is not OK.

open as a page

A gRPC call through a new reverse proxy returns HTTP 200 but its status never arrives — what broke, and how do you confirm it?

level: seniorimportance: should knowfreq 52%

basics

~20 s

An in-path hop terminated the call and did not forward the trailer section, so grpc-status was erased. Confirm by capturing at both sides of the hop: the status is present leaving the server, absent arriving at the client.

open as a page

showing 1–30 of 45