Topic Overview

gRPC: Concepts, Internals & Interview Use Cases

Learn gRPC: high-performance RPC framework using HTTP/2 and Protocol Buffers. Understand service definition, streaming, and comparison with REST.

Medium12 min read

gRPC

Why This Matters

Think of gRPC like a phone system for microservices. Instead of sending letters (REST APIs with JSON), you make phone calls (RPC calls with binary data). gRPC lets you call remote functions as if they were local, using HTTP/2 for transport and Protocol Buffers for efficient binary serialization. This makes microservices communication faster and more efficient than REST.

This matters because microservices need to communicate frequently. REST APIs with JSON are human-readable but inefficient (text-based, verbose). gRPC uses binary Protocol Buffers (smaller, faster) and HTTP/2 (multiplexing, header compression), making it much faster for service-to-service communication. Understanding gRPC helps you build efficient microservices architectures.

In interviews, when someone asks "How would you design microservices communication?", they're testing whether you understand gRPC. Do you know when to use gRPC vs REST? Do you understand Protocol Buffers? Most engineers don't. They just use REST and wonder why it's slow.

What Engineers Usually Get Wrong

Most engineers think "gRPC is just another API format." But gRPC is a complete RPC framework with code generation, streaming, and type safety. You define services in Protocol Buffer files, and gRPC generates client/server code. This provides type safety and reduces boilerplate. Understanding this helps you use gRPC effectively.

Engineers also don't understand that gRPC is designed for service-to-service communication, not browser-to-service. Browsers don't support gRPC natively (no gRPC-Web support in all browsers). Use gRPC for microservices, REST for browser APIs. Understanding this helps you choose the right protocol.

How This Breaks Systems in the Real World

A service was using REST APIs for microservices communication. Each request required JSON serialization/deserialization and HTTP/1.1 overhead. With many service calls, this became a bottleneck. The fix? Use gRPC. Binary Protocol Buffers are faster than JSON, and HTTP/2 provides multiplexing. This reduced latency by 50% and improved throughput significantly.

Another story: A service was using gRPC but didn't handle errors properly. gRPC uses status codes (not HTTP status codes), and the team wasn't checking them. Errors were silently ignored, causing bugs. The fix? Always check gRPC status codes. Handle errors appropriately. Understanding gRPC error handling helps you build reliable systems.


What is gRPC?

gRPC provides:

  • RPC framework: Call remote functions as if they were local
  • HTTP/2: Multiplexing, header compression, server push
  • Protocol Buffers: Efficient binary serialization
  • Language agnostic: Works across multiple languages
  • Streaming: Supports unary and streaming RPCs

Benefits:

  • Performance: Faster than REST (binary protocol, HTTP/2)
  • Type safety: Strong typing with Protocol Buffers
  • Code generation: Auto-generate client/server code
  • Streaming: Bidirectional streaming support

gRPC vs REST

REST (HTTP/JSON)

Client → Server: POST /api/users
  Content-Type: application/json
  Body: {"name": "John", "email": "john@example.com"}
  
Server → Client: 200 OK
  Content-Type: application/json
  Body: {"id": 1, "name": "John", "email": "john@example.com"}

Characteristics:

  • Text-based (JSON)
  • Human-readable
  • Stateless
  • Resource-oriented

gRPC (HTTP/2/Protobuf)

Client → Server: RPC call (binary)
  Method: CreateUser
  Request: (Protocol Buffer binary)
  
Server → Client: RPC response (binary)
  Response: (Protocol Buffer binary)

Characteristics:

  • Binary protocol (Protocol Buffers)
  • More efficient
  • Strong typing
  • Streaming support

Protocol Buffers

Protocol Buffers (protobuf) is a language-neutral serialization format.

Example .proto File

syntax = "proto3";

package user;

// Service definition
service UserService {
  // Unary RPC
  rpc GetUser (GetUserRequest) returns (User);
  
  // Server streaming
  rpc ListUsers (ListUsersRequest) returns (stream User);
  
  // Client streaming
  rpc CreateUsers (stream CreateUserRequest) returns (CreateUsersResponse);
  
  // Bidirectional streaming
  rpc Chat (stream Message) returns (stream Message);
}

// Message definitions
message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
}

message GetUserRequest {
  int32 id = 1;
}

message ListUsersRequest {
  int32 page = 1;
  int32 page_size = 2;
}

Key points:

  • Service: Defines RPC methods
  • Message: Data structures
  • Field numbers: Unique identifiers (1, 2, 3, ...)
  • Streaming: stream keyword for streaming RPCs

gRPC RPC Types

1. Unary RPC

One request, one response:

rpc GetUser (GetUserRequest) returns (User);
Client → Server: Request
Server → Client: Response

2. Server Streaming

One request, multiple responses:

rpc ListUsers (ListUsersRequest) returns (stream User);
Client → Server: Request
Server → Client: Response 1
Server → Client: Response 2
Server → Client: Response 3
...

3. Client Streaming

Multiple requests, one response:

rpc CreateUsers (stream CreateUserRequest) returns (CreateUsersResponse);
Client → Server: Request 1
Client → Server: Request 2
Client → Server: Request 3
Server → Client: Response

4. Bidirectional Streaming

Multiple requests, multiple responses:

rpc Chat (stream Message) returns (stream Message);
Client → Server: Request 1
Server → Client: Response 1
Client → Server: Request 2
Server → Client: Response 2
...

Examples

gRPC Server

1import * as grpc from '@grpc/grpc-js';
2import * as protoLoader from '@grpc/proto-loader';
3
4// Load proto file
5const packageDefinition = protoLoader.loadSync('user.proto', {
6 keepCase: true,
7 longs: String,
8 enums: String,
9 defaults: true,
10 oneofs: true
11});
12
13const userProto = grpc.loadPackageDefinition(packageDefinition).user as any;
14
15// Implement service
16const server = new grpc

gRPC Client

1import * as grpc from '@grpc/grpc-js';
2import * as protoLoader from '@grpc/proto-loader';
3
4// Load proto file
5const packageDefinition = protoLoader.loadSync('user.proto', {
6 keepCase: true,
7 longs: String,
8 enums: String,
9 defaults: true,
10 oneofs: true
11});
12
13const userProto = grpc.loadPackageDefinition(packageDefinition).user as any;
14
15// Create client
16const client = new userProto

gRPC with Authentication

1import * as grpc from '@grpc/grpc-js';
2
3// Server with authentication
4const server = new grpc.Server();
5
6server.addService(userProto.UserService.service, {
7 GetUser: (call: any, callback: any) => {
8 // Verify authentication
9 const metadata = call.metadata;
10 const token = metadata.get('authorization')[0];
11
12 if (!thistoken

Common Pitfalls

  • Not handling errors: gRPC uses status codes, not HTTP status codes. Fix: Handle gRPC status codes (OK, NOT_FOUND, UNAUTHENTICATED, etc.)
  • Large message sizes: Default limit is 4MB. Fix: Increase message size limit or use streaming
  • Not using streaming: Using unary for large datasets. Fix: Use server streaming for large responses
  • Version compatibility: Proto changes break clients. Fix: Use versioning, backward compatibility
  • No timeout: Requests can hang indefinitely. Fix: Set deadlines/timeouts
  • Not handling connection errors: Network issues not handled. Fix: Implement retry logic, connection pooling

Interview Questions

Beginner

Q: What is gRPC and how does it differ from REST?

A:

gRPC is a high-performance RPC framework using HTTP/2 and Protocol Buffers.

Differences from REST:

AspectRESTgRPC
ProtocolHTTP/1.1HTTP/2
FormatJSON (text)Protocol Buffers (binary)
PerformanceSlowerFaster
Type safetyWeakStrong
StreamingLimitedFull support
Code generationManualAuto-generated

gRPC Benefits:

  • Performance: Binary protocol, HTTP/2 multiplexing
  • Type safety: Strong typing with Protocol Buffers
  • Code generation: Auto-generate client/server code
  • Streaming: Bidirectional streaming support

Example:

REST:
  POST /api/users
  Content-Type: application/json
  {"name": "John"}

gRPC:
  RPC: CreateUser
  Request: (Protocol Buffer binary)

Intermediate

Q: Explain the different types of gRPC RPCs. When would you use each?

A:

1. Unary RPC:

rpc GetUser (GetUserRequest) returns (User);
  • One request, one response
  • Use when: Simple request/response (like REST)
  • Example: Get user by ID, create user

2. Server Streaming:

rpc ListUsers (ListUsersRequest) returns (stream User);
  • One request, multiple responses
  • Use when: Large dataset, real-time updates
  • Example: List users, live notifications, log streaming

3. Client Streaming:

rpc CreateUsers (stream CreateUserRequest) returns (CreateUsersResponse);
  • Multiple requests, one response
  • Use when: Batch operations, uploading data
  • Example: Batch create users, file upload

4. Bidirectional Streaming:

rpc Chat (stream Message) returns (stream Message);
  • Multiple requests, multiple responses
  • Use when: Real-time bidirectional communication
  • Example: Chat, gaming, collaborative editing

When to use:

  • Unary: Simple operations (most common)
  • Server streaming: Large datasets, real-time data
  • Client streaming: Batch operations
  • Bidirectional: Real-time communication

Senior

Q: Design a microservices architecture using gRPC. How do you handle service discovery, load balancing, retries, and observability?

A:

1class gRPCMicroservicesArchitecture {
2 private serviceRegistry: ServiceRegistry;
3 private loadBalancer: LoadBalancer;
4 private circuitBreaker: CircuitBreaker;
5 private observability: Observability;
6
7 constructor() {
8 this.serviceRegistry = new ServiceRegistry();
9 this.loadBalancer = new LoadBalancer();
10 this.circuitBreaker = new CircuitBreaker();
11 this.observability = new Observability();
12 }

Features:

  1. Service discovery: Register and discover services
  2. Load balancing: Distribute requests across instances
  3. Retry logic: Automatic retries with exponential backoff
  4. Circuit breaker: Prevent cascading failures
  5. Observability: Metrics, tracing, logging
  6. Interceptors: Middleware for cross-cutting concerns

  • HTTP/1 vs HTTP/2 vs HTTP/3 - gRPC uses HTTP/2, understanding HTTP/2 explains gRPC's multiplexing and performance benefits

  • TLS/SSL Handshake - gRPC uses TLS for secure communication, understanding TLS helps configure gRPC security

  • Connection Pooling - gRPC benefits from connection pooling, understanding pooling helps optimize gRPC performance

  • TCP vs UDP - gRPC uses TCP, understanding TCP explains gRPC's reliable communication

  • Load Balancers (L4 vs L7) - gRPC load balancing requires L7 awareness, understanding load balancers helps configure gRPC services

  • gRPC: High-performance RPC framework using HTTP/2 and Protocol Buffers

  • Protocol Buffers: Binary serialization format, more efficient than JSON

  • RPC types: Unary, server streaming, client streaming, bidirectional streaming

  • Benefits: Performance, type safety, code generation, streaming support

  • vs REST: Binary vs text, HTTP/2 vs HTTP/1.1, stronger typing

  • Service definition: Define services and messages in .proto files

  • Use cases: Microservices communication, high-performance APIs, real-time streaming

  • Best practices: Handle errors, set timeouts, use streaming for large data, implement retries and circuit breakers

Key Takeaways

gRPC: High-performance RPC framework using HTTP/2 and Protocol Buffers

Protocol Buffers: Binary serialization format, more efficient than JSON

RPC types: Unary, server streaming, client streaming, bidirectional streaming

Benefits: Performance, type safety, code generation, streaming support

vs REST: Binary vs text, HTTP/2 vs HTTP/1.1, stronger typing

Service definition: Define services and messages in .proto files

Use cases: Microservices communication, high-performance APIs, real-time streaming

Best practices: Handle errors, set timeouts, use streaming for large data, implement retries and circuit breakers


About the author

InterviewCrafted helps you master system design with patience. We believe in curiosity-led engineering, reflective writing, and designing systems that make future changes feel calm.