Skip to main content

What is gRPC?

What is gRPC gRPC is a high-performance, open-source universal RPC (Remote Procedure Call) framework initially developed by Google. It leverages HTTP/2 for transport, Protocol Buffers as the interface description language, and provides features such as authentication, load balancing, and more.
gRPC enables efficient and robust communication between services in a microservices architecture, making it a popular choice for building distributed systems and internal APIs.

What is RPC?

RPC (Remote Procedure Call) is called “remote” because it enables communications between remote services when services are deployed to different servers under microservice architecture. From the user’s point of view, it acts like a local function call. This abstraction makes distributed systems easier to build and maintain, as developers can write code that appears to call local functions while actually communicating across the network.

How gRPC Works

How gRPC Works The diagram illustrates the overall data flow for gRPC:
1

REST Call Received

A REST call is made from the client. The request body is usually in JSON format.
2

Client Transformation

The order service (gRPC client) receives the REST call, transforms it, and makes an RPC call to the payment service.gRPC encodes the client stub into a binary format and sends it to the low-level transport layer.
3

Network Transmission

gRPC sends the packets over the network via HTTP/2.Because of binary encoding and network optimizations, gRPC is said to be 5X faster than JSON.
4

Server Processing

The payment service (gRPC server) receives the packets from the network, decodes them, and invokes the server application.
5

Response Encoding

The result is returned from the server application, gets encoded, and sent to the transport layer.
6

Client Response

The order service receives the packets, decodes them, and sends the result to the client application.

Key Features of gRPC

Protocol Buffers (protobuf)

By default, gRPC uses Protocol Buffers as its Interface Definition Language (IDL).
Protocol Buffers make gRPC messages smaller and faster compared to JSON or XML.
Benefits of Protocol Buffers:
  • Binary serialization format (more compact than text)
  • Strongly typed schema
  • Backward and forward compatibility
  • Auto-generated code in multiple languages
  • Faster serialization/deserialization

HTTP/2 Based Transport

gRPC uses HTTP/2 for transport, providing many improvements over HTTP/1.x:
  • Multiplexing: Multiple requests/responses over a single connection
  • Binary Protocol: More efficient parsing
  • Header Compression: Reduced overhead
  • Server Push: Proactive data sending
  • Stream Prioritization: Control resource allocation

Multiple Language Support

gRPC supports a wide range of programming languages:
  • C++, Java, Python, Go
  • C#, Node.js, Ruby, PHP
  • Dart, Kotlin, Objective-C
  • And many more through community plugins

Bi-Directional Streaming

gRPC supports four types of communication:
// Simple request-response (like REST)
rpc GetUser (GetUserRequest) returns (User) {}
This enables development of sophisticated real-time applications with bidirectional communication like chat services, live updates, and streaming data processing.

Protocol Buffers Example

Defining a Service

syntax = "proto3";

package userservice;

// The user service definition
service UserService {
  // Unary RPC
  rpc GetUser (GetUserRequest) returns (User) {}
  
  // Server streaming RPC
  rpc ListUsers (ListUsersRequest) returns (stream User) {}
  
  // Client streaming RPC
  rpc CreateUsers (stream CreateUserRequest) returns (CreateUsersResponse) {}
  
  // Bidirectional streaming RPC
  rpc StreamUsers (stream UserRequest) returns (stream User) {}
}

// Request message
message GetUserRequest {
  string user_id = 1;
}

message ListUsersRequest {
  int32 page_size = 1;
  string page_token = 2;
}

message CreateUserRequest {
  string name = 1;
  string email = 2;
}

message UserRequest {
  string query = 1;
}

// Response messages
message User {
  string id = 1;
  string name = 2;
  string email = 3;
  int64 created_at = 4;
  repeated string roles = 5;
}

message CreateUsersResponse {
  int32 created_count = 1;
  repeated string user_ids = 2;
}

Generated Code Usage

package main

import (
    "context"
    "log"
    "net"
    
    "google.golang.org/grpc"
    pb "path/to/userservice"
)

type server struct {
    pb.UnimplementedUserServiceServer
}

func (s *server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.User, error) {
    // Implementation
    return &pb.User{
        Id:    req.UserId,
        Name:  "John Doe",
        Email: "[email protected]",
    }, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    
    s := grpc.NewServer()
    pb.RegisterUserServiceServer(s, &server{})
    
    log.Printf("server listening at %v", lis.Addr())
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

gRPC Communication Patterns

Unary RPC (Request-Response)

Most similar to traditional REST API calls:
rpc GetUser (GetUserRequest) returns (User) {}
Use Cases:
  • Simple CRUD operations
  • Authentication requests
  • Configuration retrieval

Server Streaming RPC

Client sends one request, server responds with a stream:
rpc ListUsers (ListUsersRequest) returns (stream User) {}
Use Cases:
  • Large dataset retrieval
  • Real-time notifications
  • Log streaming
  • Stock price updates

Client Streaming RPC

Client sends a stream of requests, server responds once:
rpc UploadFile (stream FileChunk) returns (UploadResponse) {}
Use Cases:
  • File uploads
  • Batch data submission
  • Sensor data collection

Bidirectional Streaming RPC

Both client and server send streams independently:
rpc Chat (stream ChatMessage) returns (stream ChatMessage) {}
Use Cases:
  • Chat applications
  • Real-time collaboration
  • Live video/audio streaming
  • Gaming

Advantages of gRPC

Performance

  • 5X faster than JSON: Binary serialization is more efficient
  • Smaller payload size: Protocol Buffers are compact
  • HTTP/2 multiplexing: Multiple requests on one connection
  • Lower latency: Reduced network overhead

Developer Productivity

  • Auto-generated code: Client and server code from .proto files
  • Strong typing: Compile-time type checking
  • Cross-language support: Polyglot microservices
  • Built-in features: Authentication, load balancing, timeouts

Scalability

  • Streaming support: Efficient for large datasets
  • Load balancing: Built-in client-side load balancing
  • Connection pooling: Efficient resource usage
  • Backpressure: Flow control mechanisms

Disadvantages of gRPC

Limited Browser Support

gRPC is not natively supported in browsers. gRPC-Web exists but requires a proxy.
  • Cannot call gRPC services directly from browsers
  • Requires gRPC-Web proxy (e.g., Envoy)
  • Not ideal for public-facing APIs

Human Readability

  • Binary format is not human-readable
  • Requires special tools to inspect messages
  • Debugging can be more challenging
  • Not suitable for public APIs where transparency is needed

Learning Curve

  • Requires learning Protocol Buffers
  • More complex than REST
  • Additional tooling needed
  • Team training required

gRPC vs REST vs GraphQL

API Comparison
AspectgRPCRESTGraphQL
ProtocolHTTP/2HTTP/1.1HTTP/1.1+
Data FormatProtocol BuffersJSONJSON
PerformanceVery HighModerateModerate
Browser SupportLimited (gRPC-Web)NativeNative
StreamingNative (4 types)Limited (SSE)Subscriptions
SchemaRequired (.proto)Optional (OpenAPI)Required (SDL)
Use CaseMicroservicesPublic APIsComplex queries

When to Use gRPC

Ideal Use Cases

  • Microservices Communication: Internal service-to-service calls
  • Real-Time Applications: Chat, gaming, live updates
  • Mobile Applications: Efficient data transfer, battery saving
  • Polyglot Environments: Multiple programming languages
  • High-Performance Requirements: Low latency, high throughput
  • Streaming Data: Large datasets, real-time processing

When REST Might Be Better

  • Public-facing APIs
  • Browser-based applications without proxy
  • Simple CRUD operations
  • Need for human-readable messages
  • Third-party integrations
  • Legacy system compatibility

Best Practices

1

Use Semantic Versioning

Version your .proto files and maintain backward compatibility.
syntax = "proto3";
package userservice.v1;
2

Implement Proper Error Handling

Use gRPC status codes for consistent error reporting.
return nil, status.Errorf(codes.NotFound, "user %s not found", req.UserId)
3

Add Timeouts and Deadlines

Prevent hanging requests with context deadlines.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
4

Use Interceptors for Cross-Cutting Concerns

Implement logging, authentication, and metrics consistently.
5

Implement Health Checks

Use gRPC health checking protocol for service monitoring.
6

Enable Compression

Use gzip compression for larger payloads when appropriate.

Security in gRPC

TLS/SSL Encryption

creds, err := credentials.NewServerTLSFromFile("server.crt", "server.key")
if err != nil {
    log.Fatalf("Failed to setup TLS: %v", err)
}
s := grpc.NewServer(grpc.Creds(creds))

Authentication

  • Token-based: Using JWT or OAuth2 tokens
  • mTLS: Mutual TLS for service-to-service
  • API Keys: Simple key-based authentication

Authorization

Implement authorization using interceptors:
func authInterceptor(ctx context.Context, req interface{}, 
    info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    // Extract and validate token from metadata
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        return nil, status.Errorf(codes.Unauthenticated, "missing metadata")
    }
    // Validate token and check permissions
    // ...
    return handler(ctx, req)
}

Key Takeaways

gRPC excels in microservices architectures where performance, streaming, and polyglot support are critical. For public APIs or browser-based applications, REST or GraphQL may be more suitable.
  • gRPC is 5X faster than JSON-based APIs due to binary serialization
  • Native support for four streaming patterns enables real-time applications
  • HTTP/2 provides multiplexing, compression, and performance benefits
  • Protocol Buffers ensure strong typing and cross-language compatibility
  • Best suited for internal microservices communication
  • Limited browser support requires gRPC-Web proxy for web applications

Build docs developers (and LLMs) love