RPC and gRPC
RPC and gRPC
Learn how Remote Procedure Call models distributed communication as method calls and how gRPC combines typed service contracts, Protocol Buffers, generated client code, HTTP/2 streams, deadlines, metadata and structured status handling.
Introduction
Distributed applications frequently need one service to request work from another service. REST models these interactions primarily around resources and HTTP semantics. Remote Procedure Call, commonly abbreviated as RPC, models communication around procedures or methods that can be invoked remotely.
An RPC client calls a method using parameters. The RPC framework serializes the request, sends it across a network, invokes the corresponding server implementation and returns a result or error.
RPC systems commonly provide:
- Service and method definitions
- Typed request and response messages
- Serialization and deserialization
- Generated client and server code
- Network communication
- Deadlines and cancellation
- Structured status handling
- Authentication metadata
- Unary and streaming operations
gRPC is an RPC framework in which a service contract defines remotely callable methods, parameters and return types. gRPC commonly uses Protocol Buffers as both its Interface Definition Language and its binary message format.
Core idea: RPC makes a remote operation appear similar to a local method call, but the operation still crosses a network. Remote calls can be delayed, duplicated by retry logic, cancelled, rejected or completed after the client stops waiting.
In your System Design curriculum, RPC and gRPC follows REST in the API Design & Service Contracts module. The module also covers GraphQL, resource modelling, pagination, versioning, idempotency, authentication versus authorization and rate-limit semantics.
Prerequisites
| # | Prerequisite | Why It Is Needed |
|---|---|---|
| 1 | REST and API contracts | RPC represents an alternative API interaction model with different trade-offs. |
| 2 | HTTP/2 | Standard gRPC communication is carried using HTTP/2 framing. |
| 3 | TLS | Production RPC communication requires appropriate transport protection and peer authentication. |
| 4 | Binary serialization | gRPC commonly exchanges Protocol Buffer messages rather than human-readable JSON. |
| 5 | Timeouts and retries | Remote method calls can fail or produce uncertain outcomes. |
| 6 | Authentication and authorization | Every protected RPC method requires identity and permission controls. |
What Is RPC?
Remote Procedure Call is a communication model in which a client invokes a procedure implemented by another process or service.
Simplified Architecture
Client Application
|
| Calls client stub
v
Generated Client Stub
|
| Serializes request
v
RPC Transport
|
| Network communication
v
RPC Server
|
| Deserializes request
v
Service Implementation
|
| Produces response
v
Generated Server Code
|
| Serializes response
v
Client receives result
Local Call vs Remote Call
| Area | Local Method Call | Remote Procedure Call |
|---|---|---|
| Execution | Occurs in the local process | Occurs in another process or service |
| Communication | Uses local memory and runtime mechanisms | Uses serialization and network communication |
| Latency | Normally low and predictable relative to networking | Includes network, queueing and remote processing time |
| Failure | Returns a result or local exception | Can fail because of timeout, connection loss, server failure or protocol errors |
| Completion certainty | Usually observable within the process | The server can complete after the client stops waiting |
| Data transfer | Passes local values or references | Transfers serialized values |
Distributed-systems rule: Do not design a remote call as if it were a reliable local function. Every remote call needs a deadline, error contract, cancellation policy and retry decision.
REST vs RPC
| Area | REST-oriented API | RPC-oriented API |
|---|---|---|
| Primary abstraction | Resources and representations | Services and methods |
| Operation expression | HTTP methods applied to resource URIs | Named remote procedures |
| Example | POST /orders |
CreateOrder() |
| Contract | HTTP semantics plus an API description | Service interface with typed messages |
| Common representation | JSON | Protocol Buffers in gRPC |
| Browser accessibility | Works naturally with browser HTTP APIs | Standard browser use normally requires a compatible bridge such as gRPC-Web |
| Streaming | Possible through HTTP streaming mechanisms | Defined as part of gRPC method types |
| Human readability | JSON requests are easy to inspect manually | Binary messages usually require schema-aware tools |
What Is gRPC?
gRPC is a framework for defining services and invoking their methods across process and network boundaries.
A gRPC design commonly includes:
- A
.protocontract file - Service definitions
- RPC method definitions
- Protocol Buffer message schemas
- Generated client stubs
- Generated server interfaces
- HTTP/2-based transport
- gRPC metadata and status codes
.proto contract
|
v
Protocol Buffer compiler
|
+--> Generated client code
|
+--> Generated server code
|
+--> Generated message classes
Protocol Buffers
Protocol Buffers provide a language-neutral mechanism for defining and serializing structured data.
A Protocol Buffer contract defines:
- Messages
- Fields
- Field types
- Stable numeric field identifiers
- Enumerations
- Services
- RPC methods
Basic Message Definition
syntax = "proto3";
package customer.v1;
message Customer {
int64 id = 1;
string name = 2;
string email = 3;
CustomerStatus status = 4;
}
enum CustomerStatus {
CUSTOMER_STATUS_UNSPECIFIED = 0;
CUSTOMER_STATUS_ACTIVE = 1;
CUSTOMER_STATUS_INACTIVE = 2;
}
The field numbers are part of the binary contract. They identify fields in serialized data and must be managed carefully during schema evolution.
Defining a gRPC Service
syntax = "proto3";
package customer.v1;
service CustomerService {
rpc GetCustomer(
GetCustomerRequest
) returns (
GetCustomerResponse
);
rpc CreateCustomer(
CreateCustomerRequest
) returns (
CreateCustomerResponse
);
rpc UpdateCustomer(
UpdateCustomerRequest
) returns (
UpdateCustomerResponse
);
rpc DeleteCustomer(
DeleteCustomerRequest
) returns (
DeleteCustomerResponse
);
}
message GetCustomerRequest {
int64 customer_id = 1;
}
message GetCustomerResponse {
Customer customer = 1;
}
message CreateCustomerRequest {
string name = 1;
string email = 2;
string idempotency_key = 3;
}
message CreateCustomerResponse {
Customer customer = 1;
}
message UpdateCustomerRequest {
int64 customer_id = 1;
string name = 2;
string email = 3;
int64 expected_version = 4;
}
message UpdateCustomerResponse {
Customer customer = 1;
}
message DeleteCustomerRequest {
int64 customer_id = 1;
}
message DeleteCustomerResponse {
}
The contract identifies remotely callable methods and the request and response types associated with every call.
Code Generation
The Protocol Buffer compiler and gRPC plugins generate language-specific code from the service contract.
protoc \
--proto_path=./proto \
--php_out=./generated \
--grpc_out=./generated \
--plugin=protoc-gen-grpc=/path/to/grpc_php_plugin \
./proto/customer/v1/customer_service.proto
Exact compiler options and plugins depend on the selected language, framework version and build environment.
Generated code can include:
- Request and response message classes
- Serialization and parsing logic
- Client stub methods
- Server-side service interfaces
- Type-safe accessors
gRPC over HTTP/2
Standard gRPC calls are carried through HTTP/2 framing. A gRPC request uses HTTP/2 headers and one or more length-prefixed messages.
gRPC Request
HTTP/2 request headers
|
v
Length-prefixed request message
|
v
End of request stream
gRPC Response
HTTP/2 response headers
|
v
Length-prefixed response message
|
v
gRPC trailers with final status
gRPC uses HTTP/2 capabilities such as multiplexed streams and long-lived connections while defining its own method, message and status conventions.
Length-prefixed Messages
+--------------------+----------------------+------------------+
| Compression Flag | Message Length | Serialized Data |
| 1 byte | 4 bytes | N bytes |
+--------------------+----------------------+------------------+
Each message identifies whether message compression is applied and carries the size of the serialized message body.
gRPC Call Types
| Call Type | Request Pattern | Response Pattern |
|---|---|---|
| Unary RPC | One request | One response |
| Server-streaming RPC | One request | Stream of responses |
| Client-streaming RPC | Stream of requests | One response |
| Bidirectional-streaming RPC | Stream of requests | Stream of responses |
Unary RPC
rpc GetCustomer(
GetCustomerRequest
) returns (
GetCustomerResponse
);
Client sends one request
|
v
Server performs operation
|
v
Server returns one response
Unary RPC resembles a traditional request-response method call.
Server-streaming RPC
rpc WatchOrder(
WatchOrderRequest
) returns (
stream OrderUpdate
);
Client sends one request
|
v
Server sends update 1
|
v
Server sends update 2
|
v
Server sends update 3
|
v
Server completes response stream
This is useful for:
- Progress updates
- Monitoring events
- Change notifications
- Large result streams
Client-streaming RPC
rpc UploadMeasurements(
stream Measurement
) returns (
UploadSummary
);
Client sends message 1
Client sends message 2
Client sends message 3
Client completes request stream
|
v
Server returns one summary response
This is useful for:
- Batch uploads
- Telemetry submission
- Incremental file processing
- Aggregating client events
Bidirectional Streaming
rpc Collaborate(
stream CollaborationCommand
) returns (
stream CollaborationEvent
);
Client Server
| |
| Request message 1 |
|----------------------------------------->|
| |
| Response message 1 |
|<-----------------------------------------|
| |
| Response message 2 |
|<-----------------------------------------|
| |
| Request message 2 |
|----------------------------------------->|
| |
| Independent message flow |
|<========================================>|
Request and response streams operate independently. The application protocol must define message correlation, ordering, completion, acknowledgements and error behaviour.
Deadlines
Every remote call should use a finite deadline. A deadline defines how long the client is willing to wait for the complete operation.
Client starts RPC
|
v
Deadline begins
|
+--> Response arrives before deadline:
| return result
|
+--> Deadline expires:
cancel local wait
propagate cancellation where supported
return deadline error
Uncertain outcome: A client deadline expiring does not prove that the server made no change. The server might have committed the operation before cancellation was observed.
A deadline should account for:
- Connection establishment
- TLS negotiation
- Queueing
- Server processing
- Downstream calls
- Response transfer
Cancellation
Cancellation communicates that the caller no longer needs the operation. Server implementations should observe the cancellation context and stop unnecessary work when safe.
Client cancels call
|
v
gRPC runtime communicates cancellation
|
v
Server observes cancellation
|
+--> Work can stop safely:
| release resources
|
+--> Operation already committed:
preserve committed outcome
avoid unsafe rollback assumptions
Cancellation is cooperative. It does not guarantee that the remote operation was never started or completed.
Retries
A failed RPC can be retried only when the method contract and failure state make repetition safe.
RPC fails or times out
|
v
Can the operation be safely repeated?
|
+--> No:
| return uncertain outcome
|
+--> Yes:
apply bounded retry
with backoff and jitter
Retry design should define:
- Retryable status codes
- Maximum attempts
- Backoff policy
- Randomized jitter
- Complete operation deadline
- Idempotency requirements
- Retry ownership
Idempotency
Read operations such as GetCustomer can naturally support safe
repetition. Creation, payment and workflow commands require explicit
idempotency design.
message CreateOrderRequest {
string idempotency_key = 1;
int64 customer_id = 2;
repeated OrderLine items = 3;
}
First call with key K:
Validate key
Create order
Store result for key K
Return order
Retry with key K and identical request:
Find stored result
Do not create another order
Return original result
Key K with different request:
Reject as a conflict
gRPC Status Codes
gRPC returns a structured status containing a status code and optional error information.
| Status | Typical Meaning |
|---|---|
OK |
The operation completed successfully |
CANCELLED |
The operation was cancelled |
UNKNOWN |
An unknown error occurred |
INVALID_ARGUMENT |
The request contains invalid arguments |
DEADLINE_EXCEEDED |
The operation did not complete before its deadline |
NOT_FOUND |
The requested entity was not found |
ALREADY_EXISTS |
An entity that the caller attempted to create already exists |
PERMISSION_DENIED |
The caller lacks permission for the operation |
UNAUTHENTICATED |
Valid authentication credentials are missing |
RESOURCE_EXHAUSTED |
An applicable quota or capacity limit was exceeded |
FAILED_PRECONDITION |
The system is not in a state required for the operation |
ABORTED |
The operation was aborted because of a conflict |
OUT_OF_RANGE |
The requested operation is outside an allowed range |
UNIMPLEMENTED |
The operation is unsupported or not implemented |
INTERNAL |
An internal invariant or processing failure occurred |
UNAVAILABLE |
The service is temporarily unavailable |
DATA_LOSS |
Unrecoverable data loss or corruption was detected |
Error Contract
A service should return stable machine-readable error information without exposing internal stack traces, SQL statements or infrastructure details.
{
"code": "INVALID_ARGUMENT",
"message": "Request validation failed.",
"details": [
{
"field": "email",
"reason": "invalid_format"
}
],
"traceId": "trace-8f21"
}
An error contract should distinguish:
- Client validation errors
- Authentication failures
- Authorization failures
- Missing entities
- State conflicts
- Deadline expiration
- Temporary service unavailability
- Unexpected internal failures
Metadata
gRPC metadata carries additional call information using HTTP/2 fields.
Metadata can carry:
- Authentication credentials
- Correlation identifiers
- Tracing context
- Locale preferences
- Client-version information
- Application-specific request context
authorization: Bearer ACCESS_TOKEN
x-correlation-id: request-1042
traceparent: trace-context-value
accept-language: en-US
Metadata rule: Metadata is part of the request contract and must be validated, size-limited and protected. Credentials and sensitive metadata must not be written to ordinary logs.
Authentication
Authentication establishes the identity of the calling service, user or workload.
Common approaches include:
- TLS server authentication
- Mutual TLS
- Bearer access tokens
- Signed workload credentials
- Service-mesh identity
Client establishes protected connection
|
v
Client presents credential
|
v
Server validates credential
|
v
Caller identity is established
|
v
Method authorization is evaluated
Authorization
Every protected method requires an authorization decision. Authorization should consider both the method and the target entity.
Authenticated caller
|
v
Calls GetCustomer(customer_id = 42)
|
v
Load customer 42
|
v
Evaluate permission for customer 42
|
+--> Allowed:
| return customer
|
+--> Denied:
return permission error
Do not authorize access only because the request contains a syntactically valid entity identifier.
TLS and Mutual TLS
gRPC connections should use TLS when communication requires protected transport. Mutual TLS additionally validates client certificates.
Server-authenticated TLS:
Client validates server certificate.
Mutual TLS:
Client validates server certificate.
Server validates client certificate.
Certificate identity establishes an authenticated context. Business authorization remains a separate service decision.
Flow Control and Backpressure
Streaming methods need backpressure so a fast producer cannot create unlimited buffered data for a slow consumer.
Fast producer
|
v
Bounded application queue
|
v
gRPC and HTTP/2 flow control
|
v
Slow consumer
A streaming contract should define:
- Maximum message size
- Maximum queued messages
- Maximum queued bytes
- Consumer cancellation behaviour
- Producer waiting behaviour
- Whether data can be coalesced or discarded
Message-size Limits
Every incoming and outgoing message should have explicit size limits.
Unbounded messages can cause:
- Memory exhaustion
- Long serialization pauses
- High network latency
- Slow garbage collection
- Resource-exhaustion attacks
Large datasets should normally be paginated, streamed or transferred through a purpose-built storage and download mechanism.
Protocol Buffer Compatibility
Protocol Buffer contracts should evolve without changing the meaning of existing field numbers.
Compatible Additive Change
message Customer {
int64 id = 1;
string name = 2;
string email = 3;
string preferred_language = 4;
}
Do Not Reuse Removed Field Numbers
message Customer {
int64 id = 1;
string name = 2;
reserved 3;
reserved "email";
}
Reserving removed numbers and names prevents accidental reuse that could cause old and new clients to interpret data differently.
Field-number Rules
Schema Evolution Practices
- Never change the meaning of an existing field number.
- Do not reuse a deleted field number.
- Reserve deleted field numbers and names.
- Add new fields using new numbers.
- Avoid changing an existing field to an incompatible type.
- Design default-value behaviour carefully.
- Include an unspecified zero value in enumerations.
- Do not assume every client upgrades at the same time.
- Run compatibility checks in the build pipeline.
Field Presence
APIs must distinguish when necessary between:
- A field that was not sent
- A field sent with its default value
- A field explicitly cleared
- A field inherited from existing state
message UpdateCustomerRequest {
int64 customer_id = 1;
optional string name = 2;
optional string email = 3;
}
Presence-aware fields help prevent partial-update APIs from treating an omitted value as an instruction to clear existing data.
Field Masks
Field masks can identify fields that a caller intends to update.
import "google/protobuf/field_mask.proto";
message UpdateCustomerRequest {
Customer customer = 1;
google.protobuf.FieldMask update_mask = 2;
int64 expected_version = 3;
}
Customer values:
name = "Updated Name"
email = "new@example.com"
Update mask:
paths:
- name
Result:
Only name is changed.
Email retains its existing value.
Optimistic Concurrency
message UpdateCustomerRequest {
Customer customer = 1;
int64 expected_version = 2;
}
Client reads:
customer version = 7
Client submits update:
expected_version = 7
Server verifies:
Current version is 7:
Apply update and create version 8.
Current version is not 7:
Reject the stale update.
Version checking prevents one caller from unknowingly overwriting changes made by another caller.
Health Checking
A production gRPC service should expose health information through an appropriate health-checking contract.
Health checks can distinguish:
- Process liveness
- Service readiness
- Serving status
- Dependency degradation
A healthy process does not prove that every method and dependency is ready for production traffic.
Server Reflection
Server reflection can allow compatible tools to discover available gRPC services and descriptors at runtime.
Reflection is useful for authorized development and diagnostic tooling, but production exposure should follow the service's security and information- disclosure policy.
Load Balancing
gRPC commonly reuses long-lived HTTP/2 connections. Connection reuse affects how traffic is distributed across backend instances.
Client
|
| Long-lived HTTP/2 connection
v
Load Balancer
|
v
Backend A
Without suitable balancing design:
Many RPC calls on that connection
can continue reaching Backend A.
A balancing design can consider:
- Client-side load balancing
- Proxy-based load balancing
- Name resolution
- Health checking
- Connection lifetime
- Backend draining
- Retry and failover policy
Graceful Shutdown
Deployment begins
|
v
Stop accepting new calls
|
v
Mark instance not ready
|
v
Allow in-flight calls to finish
|
v
Cancel calls after shutdown deadline
|
v
Close connections and stop process
Streaming calls require a defined drain, cancellation and reconnection policy.
Browser Compatibility
Standard browser APIs do not generally expose the complete gRPC HTTP/2 protocol directly. Browser applications commonly use gRPC-Web or a compatible gateway.
Browser
|
| gRPC-Web request
v
gRPC-Web Proxy or Gateway
|
| Standard gRPC
v
gRPC Backend Service
The gateway becomes part of the contract and must handle authentication, CORS, translation, limits, errors and observability correctly.
REST Gateway
Some architectures expose REST or JSON externally while using gRPC between backend services.
External Client
|
| REST and JSON
v
API Gateway
|
| Translates request
v
Internal gRPC Service
The translation contract should define:
- HTTP method and URI mapping
- JSON-to-Protobuf conversion
- Status-code mapping
- Error-detail mapping
- Authentication propagation
- Deadline propagation
- Streaming limitations
Interceptors
Interceptors can apply cross-cutting logic around client or server calls.
Common interceptor responsibilities include:
- Authentication
- Authorization context
- Correlation identifiers
- Tracing
- Metrics
- Structured logging
- Retry policy
- Validation
Interceptor rule: Cross-cutting middleware should not hide method-specific authorization, validation or idempotency requirements.
Observability
Useful gRPC telemetry includes:
- Calls per method
- Latency percentiles per method
- Status-code distribution
- Deadline-exceeded count
- Cancellation count
- Retry count
- Request and response message sizes
- Active streaming calls
- Messages per stream
- Authentication and authorization failures
- Backend connection state
- Queue depth and backpressure
Logs should identify the method, status, duration and trace context without recording credentials or sensitive message contents.
Test with grpcurl
List Available Services
grpcurl \
api.example.com:443 \
list
Describe a Service
grpcurl \
api.example.com:443 \
describe customer.v1.CustomerService
Invoke a Unary Method
grpcurl \
-H 'authorization: Bearer ACCESS_TOKEN' \
-d '{"customerId":"42"}' \
api.example.com:443 \
customer.v1.CustomerService/GetCustomer
Listing and describing services require server reflection or locally supplied descriptors. Do not place production credentials directly in shell history.
Inspect HTTP/2 Connections
ss -tnp
openssl s_client \
-connect api.example.com:443 \
-servername api.example.com \
-alpn h2
These commands can confirm transport connections and ALPN negotiation, but a gRPC-aware client is required to validate method-level behaviour.
Troubleshooting Workflow
- Confirm the package, service and method names.
- Confirm the deployed contract version.
- Resolve the server name and verify routing.
- Confirm TCP and TLS connectivity.
- Confirm HTTP/2 negotiation.
- Inspect authentication metadata.
- Record the gRPC status code and safe error details.
- Check the call deadline and cancellation state.
- Inspect message-size and flow-control limits.
- Check retries and idempotency handling.
- Use the trace identifier to inspect downstream calls.
- Compare runtime behaviour with the deployed
.protocontract.
Common RPC and gRPC Mistakes
Treating a Remote Call as a Local Function
Remote calls have network latency, partial failures, cancellation and uncertain outcomes.
Using Infinite Deadlines
Calls can retain threads, connections and downstream resources indefinitely.
Retrying Every Failure
Some failures are permanent, and some methods can create duplicate business effects.
Reusing Protocol Buffer Field Numbers
Old and new clients can interpret the same serialized field differently.
Changing Field Types Incompatibly
Generated clients and stored messages can become incompatible with the changed schema.
Sending Large Unary Messages
Large messages increase serialization, memory, transport and retry costs. Use pagination, streaming or object storage where appropriate.
Using Streaming without Backpressure
A fast producer can create unbounded buffers for a slow consumer.
Ignoring Cancellation
The server can continue expensive work after the caller no longer needs the result.
Logging Complete Metadata
Metadata can contain access credentials, identity information and tracing values that require protection.
Assuming Authentication Grants Every Method
Every method and target entity requires an authorization decision.
Using One Long-lived Connection without Balancing Awareness
Connection reuse can concentrate calls on one backend unless the balancing architecture accounts for gRPC connection behaviour.
Publishing a Contract without Compatibility Tests
Schema checks and integration tests should verify that old and new clients remain compatible according to policy.
Recommended Test Cases
| Test | Expected Evidence |
|---|---|
| Valid unary call | The expected typed response and OK status are returned |
| Invalid request | The method returns a structured validation error |
| Unauthenticated call | The call is rejected without executing protected work |
| Unauthorized entity | The caller cannot access another tenant's or user's entity |
| Deadline expiration | The call ends within the configured deadline |
| Cancellation | The server stops unnecessary work when cancellation is observed |
| Duplicate create retry | The idempotency contract prevents duplicate effects |
| Stale update | The expected-version check rejects the conflicting request |
| Oversized message | The message is rejected without uncontrolled memory growth |
| Slow stream consumer | The backpressure and queue policy is applied |
| Schema compatibility | Old and new clients interpret supported messages correctly |
| Backend shutdown | Calls drain, fail over or return controlled statuses according to policy |
RPC and gRPC Best Practices
Recommended Practices
- Design every remote call as a fallible network operation.
- Define typed request and response contracts.
- Use finite deadlines on every call.
- Propagate deadlines to downstream calls.
- Observe cancellation and release resources promptly.
- Retry only documented transient failures.
- Use idempotency protection for retryable state-changing methods.
- Use bounded retries with exponential backoff and jitter.
- Apply request, response and stream message-size limits.
- Use bounded application queues and backpressure.
- Authenticate every protected connection or call.
- Authorize every method and target entity.
- Use TLS and mTLS according to the trust model.
- Never reuse removed Protocol Buffer field numbers.
- Reserve deleted fields and names.
- Prefer additive schema evolution.
- Monitor methods, statuses, deadlines, retries and stream counts.
- Drain long-lived calls during deployments.
- Test generated clients across supported languages.
- Keep the deployed implementation aligned with the published contract.
Practice Exercise
Design a gRPC service for customer and order operations and compare it with the earlier REST API.
Requirements
- Define versioned package names.
- Define customer and order messages.
- Implement a unary customer lookup.
- Implement idempotent order creation.
- Implement a server stream for order-status updates.
- Implement a client stream for telemetry upload.
- Apply finite deadlines.
- Propagate cancellation to database and downstream operations.
- Authenticate callers through protected metadata or mTLS.
- Authorize every customer and order operation.
- Apply request and response message-size limits.
- Use expected versions for updates.
- Return structured gRPC statuses.
- Expose an authorized health-check service.
- Add compatibility tests for the
.protocontract.
Suggested Service Contract
syntax = "proto3";
package order.v1;
service OrderService {
rpc GetOrder(
GetOrderRequest
) returns (
GetOrderResponse
);
rpc CreateOrder(
CreateOrderRequest
) returns (
CreateOrderResponse
);
rpc WatchOrder(
WatchOrderRequest
) returns (
stream OrderUpdate
);
}
message GetOrderRequest {
int64 order_id = 1;
}
message GetOrderResponse {
Order order = 1;
}
message CreateOrderRequest {
string idempotency_key = 1;
int64 customer_id = 2;
repeated OrderLine lines = 3;
}
message CreateOrderResponse {
Order order = 1;
}
message WatchOrderRequest {
int64 order_id = 1;
int64 after_version = 2;
}
message OrderUpdate {
int64 order_id = 1;
int64 version = 2;
OrderStatus status = 3;
string occurred_at = 4;
}
message OrderLine {
string product_id = 1;
int32 quantity = 2;
}
message Order {
int64 id = 1;
int64 customer_id = 2;
repeated OrderLine lines = 3;
OrderStatus status = 4;
int64 version = 5;
}
enum OrderStatus {
ORDER_STATUS_UNSPECIFIED = 0;
ORDER_STATUS_PENDING = 1;
ORDER_STATUS_CONFIRMED = 2;
ORDER_STATUS_PROCESSING = 3;
ORDER_STATUS_COMPLETED = 4;
ORDER_STATUS_CANCELLED = 5;
}
Frequently Asked Questions
What is RPC?
RPC is a communication model in which a client invokes a procedure implemented by another process or service.
What is gRPC?
gRPC is an RPC framework based on service definitions, typed messages, generated code and an HTTP/2-based protocol.
What are Protocol Buffers?
Protocol Buffers provide a language-neutral mechanism for defining and serializing structured messages.
Does gRPC require Protocol Buffers?
Protocol Buffers are the default gRPC interface-definition and message format, although gRPC can support other formats through compatible implementations.
What are the four gRPC call types?
The four types are unary, server streaming, client streaming and bidirectional streaming.
Why does every RPC need a deadline?
Without a deadline, a failed or stalled dependency can retain client, server and downstream resources indefinitely.
Does cancellation guarantee that the operation did not complete?
No. The server can complete or commit an operation before observing the cancellation.
Can every failed gRPC call be retried?
No. Retry only when the status and method contract make repetition safe.
Why should Protocol Buffer field numbers not be reused?
Reuse can cause old and new clients to interpret the same serialized data as different fields.
Can browsers call standard gRPC directly?
Browser applications commonly require gRPC-Web or a compatible gateway rather than using the complete standard gRPC HTTP/2 protocol directly.
When is gRPC a good choice?
gRPC is well suited to typed service-to-service APIs, polyglot backend systems and applications requiring unary or streaming method contracts.
What comes after RPC and gRPC?
The next topic is GraphQL, followed by resource modelling and pagination.
Key Takeaway
RPC models distributed communication as remote method calls, while gRPC combines typed service definitions, Protocol Buffer messages, generated client and server code and HTTP/2 communication. gRPC supports unary, server-streaming, client-streaming and bidirectional-streaming calls. Production contracts must define deadlines, cancellation, status codes, retries, idempotency, authentication, authorization, message limits, backpressure and schema compatibility. A generated stub makes calling a remote method convenient, but the call remains a fallible distributed operation.