gRPC Client and Server Stubs

gRPC stubs are generated, language-specific classes that make remote procedure calls look like ordinary method calls. In Java, a client stub sends requests through gRPC, while server-side generated types help connect your service implementation to the gRPC runtime.

A gRPC service is normally defined in a `.proto` file. Code generation produces Java types for the service, messages, and RPC methods, so application code does not need to manually construct the underlying protocol messages or manage the RPC transport directly.

On the client side, a generated stub exposes RPC methods such as unary or streaming calls. The stub uses a gRPC `Channel` to communicate with the remote server; the application supplies request objects and receives responses or stream callbacks depending on the RPC style.

On the server side, generated code typically provides an abstract base class or service interface that the application extends or implements. The developer supplies the business logic, while the generated service machinery maps incoming RPCs to that implementation and handles integration with the gRPC server runtime.

Java gRPC commonly provides different client stub forms for different calling patterns. A blocking stub is convenient for synchronous unary calls, while an asynchronous stub uses callbacks or observers and is appropriate when the caller should not block waiting for the response. A future-based stub can represent a unary result as a future.

Stubs are generated from the service definition rather than handwritten for each endpoint. This keeps client and server APIs consistent with the `.proto` contract and reduces repetitive serialization, transport, and dispatch code.

Key points

Interview questions

How does a generated stub know which remote method to invoke?

The service and RPC declarations in the `.proto` file define the methods and their request and response message types. The gRPC code generator uses that contract to create language-specific service and stub classes. Generated metadata associates each method with its gRPC service and method name. When the stub method is called, the gRPC runtime uses that metadata to perform the corresponding RPC over the channel.

What is a gRPC client stub?

A gRPC client stub is generated code that exposes remote service methods as language-specific APIs. In Java, the application can call a generated stub method with a generated request object instead of manually constructing the underlying RPC message. The stub uses a gRPC channel to communicate with the server. This gives the client a typed interface derived from the `.proto` service definition.

What is the difference between a client stub and the server-side generated code?

The client stub is used by a client application to initiate RPC calls. Server-side generated code provides the structure needed to register and dispatch those RPCs to the application's service implementation. The generated server-side type does not normally contain the application's business rules. Instead, the developer implements the service methods and lets the gRPC runtime handle transport and dispatch.

What is the difference between blocking and asynchronous gRPC stubs in Java?

A blocking stub makes a unary RPC call synchronously and returns the response after the operation completes. An asynchronous stub returns control to the caller while the result is delivered through an observer or callback mechanism. Blocking calls are straightforward but can tie up threads while waiting. Asynchronous calls can be useful when the application needs non-blocking execution or streaming responses.

Why are generated stubs useful in a large Java backend?

Generated stubs establish a consistent typed boundary between services without requiring each team to handwrite transport code. They reduce boilerplate for request construction, serialization, RPC invocation, and service dispatch. Because the API is derived from a shared contract, changes to the service definition can be detected during compilation or code generation rather than only at runtime. The main engineering concern is then managing contract compatibility, generated-code versions, channel lifecycle, deadlines, and failure handling.