5 exercises — Practice gRPC and Protobuf vocabulary in English: .proto file, message types, field numbers, stubs, channels, streaming RPC patterns, status codes, interceptors, and deadlines.
Streaming: unary RPC, server streaming, client streaming, bidirectional streaming
Operations: status codes (OK, UNAVAILABLE, DEADLINE_EXCEEDED), interceptor, deadline/timeout, health check protocol
0 / 5 completed
1 / 5
A backend engineer introduces gRPC to a team migrating from REST: "gRPC is a high-performance RPC framework from Google. Instead of JSON over HTTP/1.1, we use Protocol Buffers for serialization and HTTP/2 for transport. You define your service and messages in a .proto file — this is the contract. The protoc compiler generates client stubs and server interfaces in your language of choice. The stub is what the client calls — it looks like a local function call but actually makes a network RPC. The channel is the connection to the server, managing HTTP/2 multiplexing, load balancing, and TLS." What is a stub in gRPC and how does it relate to the .proto file?
Stub (generated client): when you run protoc with the gRPC plugin on a .proto file, it generates two things: (1) message classes for serialization/deserialization, (2) stub classes for the client and base classes for the server. The stub encapsulates: serialize request to Protobuf binary, open HTTP/2 stream on the channel, send request, receive response bytes, deserialize to response message type. .proto file structure: syntax = "proto3"; — declares proto3 syntax. package: namespacing. message: defines a data type. service: defines an RPC interface. rpc: declares a method. Protobuf field numbers: each field has a number (1, 2, 3...). This number is used in the binary encoding, not the field name. Field numbers 1-15 use one byte in encoding. Never change existing field numbers — breaks wire compatibility. Wire format vocabulary: Varint: variable-length integer encoding. Length-delimited: for strings, bytes, embedded messages. In conversation: 'The stub is magic — it makes calling a service in another language on another continent look like calling a local function. The .proto is the contract that makes that possible.'
2 / 5
A senior engineer explains gRPC streaming to a developer building a real-time chat service: "gRPC has four RPC patterns. Unary is like REST: one request, one response. Server streaming: you send one request, the server sends back a stream of responses — great for live feeds. Client streaming: you send a stream of requests, get one response — good for file uploads. Bidirectional streaming: both sides send streams simultaneously over one HTTP/2 connection — perfect for chat or collaborative editing. HTTP/2 multiplexes all of this on a single TCP connection, unlike HTTP/1.1 which needs a new connection per request." What makes bidirectional streaming RPC possible in gRPC but not in standard REST?
HTTP/2 multiplexing: HTTP/2 introduces streams — multiple independent request-response sequences sharing one TCP connection. Each stream has a unique ID. Frames from different streams are interleaved. gRPC maps each RPC call to an HTTP/2 stream. Bidirectional streaming: both client and server can send frames on their respective streams at any time. .proto streaming syntax: rpc Chat(stream ChatMessage) returns (stream ChatMessage); — both request and response are streams. Four patterns: Unary: one request, one response. Server streaming: one request, stream of responses. Client streaming: stream of requests, one response. Bidi streaming: streams in both directions. HTTP/2 benefits for gRPC: header compression (HPACK), binary framing, flow control. gRPC-Web: browser clients cannot use gRPC directly. gRPC-Web is a translation layer (Envoy proxy) that adapts for browser fetch/XHR. In conversation: 'For internal service-to-service calls, gRPC bidi streaming eliminated our polling architecture entirely. Latency dropped from 200ms polling to sub-5ms push latency.'
3 / 5
An SRE explains a production timeout incident caused by a missing gRPC configuration: "The recommendation service call was hanging. The ML model it called occasionally takes 30 seconds on a cold cache. Our client had no deadline set — it waited indefinitely, holding a thread. Under load, all threads were blocked waiting for the ML service. The fix: set a deadline of 500ms on every gRPC call. If the ML service doesn't respond in time, we return a DEADLINE_EXCEEDED status and show a fallback. Never make a gRPC call without a deadline — it's the same as writing a network call with no timeout." What is a deadline in gRPC and why is it preferable to a simple timeout?
Deadline: an absolute timestamp by which the entire operation must complete. Passed in the gRPC context. When ServiceA calls ServiceB calls ServiceC, the deadline propagates — each downstream service sees the remaining time budget. If the deadline passes, the call is cancelled at all levels simultaneously. Timeout: a duration relative to the current call. Does not propagate — each service in a chain might set its own timeout. gRPC status codes: OK (0): success. CANCELLED (1): operation cancelled. DEADLINE_EXCEEDED (4): deadline expired. NOT_FOUND (5): entity not found. PERMISSION_DENIED (7): caller lacks permission. RESOURCE_EXHAUSTED (8): quota/rate limit. UNAVAILABLE (14): service unavailable — safe to retry. UNAUTHENTICATED (16): not authenticated. In conversation: 'Always propagate the context with its deadline to downstream calls. One gRPC call that hangs indefinitely can cascade into thread-pool exhaustion across your entire service mesh.'
4 / 5
A developer explains a backward compatibility issue discovered during API evolution: "We removed the 'phone_number' field from the User message and freed field number 4 for a new field 'profile_picture_url'. Old clients started getting garbled data — 'profile_picture_url' was being deserialized as 'phone_number'. Protobuf uses field numbers for encoding, not field names. Reusing field number 4 was the mistake. We should have used 'reserved 4; reserved "phone_number";' to prevent future misuse. Lesson: never reuse field numbers." Why are field numbers in Protobuf critical for backward compatibility?
Protobuf wire format: each field is encoded as (field_number << 3 | wire_type), followed by the value. Field names are NOT in the binary encoding. An old decoder seeing field 4 uses its schema to interpret it. Safe Protobuf changes: add new fields (old code ignores unknown fields), remove optional fields (new code gets default). Unsafe changes: change field type, change field number, reuse a field number. reserved keyword: reserved 4; reserved "phone_number"; prevents both the number and name from being reused. The compiler errors if you try. Proto3 default values: missing fields get language defaults — 0 for numbers, "" for strings, false for bool. Use google.protobuf.Int32Value wrapper for nullable scalars. Well-known types: Timestamp, Duration, Struct, Any, FieldMask — standard Protobuf types for common patterns. In conversation: 'Field numbers are forever. Document removed fields with reserved. It takes 30 seconds and saves hours of debugging mismatched data across service versions.'
5 / 5
A platform engineer explains gRPC interceptors during a developer onboarding session: "We use interceptors — gRPC's equivalent of middleware — for all our cross-cutting concerns. There's an auth interceptor that validates JWT tokens on every inbound call. A logging interceptor that records every request: method name, latency, status code. A tracing interceptor that starts an OpenTelemetry span and propagates trace context to downstream calls. A retry interceptor on the client side that retries UNAVAILABLE errors with exponential backoff. Interceptors chain — each wraps the next, passing down the context." What is a gRPC interceptor and what is it used for?
gRPC interceptor: analogous to middleware in web frameworks. Wraps the RPC handler in a chain. Types: Unary interceptor: wraps single request-response RPCs. Stream interceptor: wraps streaming RPCs. Client-side: runs in the caller's process before sending. Server-side: runs in the server's process before the handler. Common patterns: Auth interceptor (server-side): extract token from metadata, validate, attach user context. Return UNAUTHENTICATED if invalid. Logging interceptor: log method name, peer address, status code and latency. Tracing interceptor: start span, extract/inject trace context headers (W3C Trace Context). Retry interceptor (client-side): on UNAVAILABLE, retry with exponential backoff. gRPC metadata vocabulary: Metadata: key-value pairs sent with an RPC, analogous to HTTP headers. Used for: auth tokens, trace IDs, client version. Trailing metadata: sent by server after the response body (HTTP/2 trailers). gRPC health check protocol: standard proto that servers implement to report readiness. Used by Kubernetes probes and load balancers. In conversation: 'Interceptors are where your operational concerns live. The handler should be pure business logic. Authentication, tracing, retry — interceptors.'