Skip to content
0xbenzo
Back to writing
6 min read

Understanding gRPC & Protocol Buffers

Learn what gRPC and Protocol Buffers are, how they work together, and why they have become the preferred communication technology for modern microservices and cloud-native applications.

Introduction

When building applications, different services often need to communicate with each other. Traditionally, this communication happens through REST APIs, where data is exchanged in JSON format over HTTP.

REST is simple, human-readable, and widely supported, making it an excellent choice for public APIs. However, as systems grow into distributed architectures with dozens or even hundreds of services, the overhead of JSON parsing and HTTP/1.1 becomes more noticeable.

This is where gRPC and Protocol Buffers (Protobuf) come in. Together, they provide a fast, strongly typed, and efficient way for applications to communicate.


What is RPC?

RPC stands for Remote Procedure Call.

The idea is simple: instead of manually sending HTTP requests and parsing responses, you call a function that executes on another machine as if it were a local function.

Instead of writing:

GET /users/101

you simply write:

user, err := client.GetUser(ctx, request)

The networking happens behind the scenes.

Application

GetUser()


Network


Remote Server

Execute Function

This abstraction makes distributed systems easier to build and maintain.


What is gRPC?

gRPC (Google Remote Procedure Call) is an open-source RPC framework originally developed by Google.

It provides everything needed for communication between services:

  • High-performance networking
  • Automatic code generation
  • Built-in serialization
  • HTTP/2 support
  • Streaming
  • Authentication support
  • Cross-language compatibility

Instead of manually implementing APIs, you define your service once and let gRPC generate the client and server code.


What is Protocol Buffers?

Protocol Buffers (Protobuf) is Google’s binary serialization format.

Think of it as a faster and more compact alternative to JSON.

JSON:

{
  "id": 101,
  "name": "Alice"
}

Protobuf sends the same information as compact binary data instead of readable text.

Although binary data isn’t human-readable, it is much smaller and significantly faster for computers to process.


The .proto File

Every gRPC application starts with a .proto file.

It acts as a blueprint that defines:

  • Data structures
  • Services
  • RPC methods

Example:

syntax = "proto3";

package user;

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

Here:

  • message defines a data structure.
  • int32, string, and other scalar types define field types.
  • The numbers (1, 2, 3) are unique field identifiers used in binary serialization.

These field numbers should never be changed once the API is published, as they are part of the serialized data format.


Defining Services

Besides defining data, .proto files also define APIs.

service UserService {

    rpc GetUser(GetUserRequest)
        returns (User);

    rpc CreateUser(CreateUserRequest)
        returns (User);
}

This tells gRPC:

  • A service named UserService exists.
  • It has two RPC methods.
  • Each method accepts a request message and returns a response message.

This single file becomes the source of truth for every client and server.


Code Generation

One of gRPC’s biggest strengths is automatic code generation.

Running the Protocol Buffer compiler:

protoc \
  --go_out=. \
  --go-grpc_out=. \
  user.proto

generates:

user.pb.go
user_grpc.pb.go

These files contain:

  • Go structs
  • Serialization logic
  • Client implementation
  • Server interface

No boilerplate networking code needs to be written manually.


Understanding Stubs

Stubs are generated proxy classes that make remote communication feel like local function calls.

There are two types of stubs:

Client Stub

The client stub is used by the application to call remote services.

client := pb.NewUserServiceClient(conn)

user, err := client.GetUser(ctx, &pb.GetUserRequest{
    Id: 101,
})

Although it looks like a normal function call, the stub automatically:

  • Serializes the request using Protocol Buffers.
  • Sends it over HTTP/2.
  • Waits for the response.
  • Deserializes the response.
  • Returns the result.
Application

GetUser()

Client Stub

HTTP/2

Server

Server Stub

The server stub is also generated automatically.

It exposes an interface that developers implement.

type UserServer struct {
    pb.UnimplementedUserServiceServer
}

func (s *UserServer) GetUser(
    ctx context.Context,
    req *pb.GetUserRequest,
) (*pb.User, error) {

    return &pb.User{
        Id: req.Id,
        Name: "Alice",
    }, nil
}

The server stub handles:

  • Receiving requests
  • Parsing binary data
  • Calling your implementation
  • Serializing responses

You only write the business logic.


Why HTTP/2?

Unlike REST, which commonly uses HTTP/1.1, gRPC uses HTTP/2.

HTTP/2 provides several important improvements:

  • Multiplexing (multiple requests over one connection)
  • Header compression
  • Binary framing
  • Persistent connections
REST

Connection 1

Connection 2

Connection 3

-------------------

gRPC

Single Connection

├── Stream 1

├── Stream 2

├── Stream 3

This reduces latency and improves throughput.


Types of RPC

gRPC supports four communication patterns.

1. Unary RPC

One request, one response.

Client ----> Server

Client <---- Server

Similar to a REST API call.


2. Server Streaming

One request, multiple responses.

Client ---->

Server

Response 1

Response 2

Response 3

Useful for:

  • Logs
  • Metrics
  • Notifications

3. Client Streaming

Multiple requests, one response.

Client

Data 1

Data 2

Data 3

--------->

Server

Summary

Useful for uploading batches of data.


4. Bidirectional Streaming

Both client and server send data simultaneously.

Client <==================> Server

Useful for:

  • Chat applications
  • Live dashboards
  • Monitoring agents
  • Real-time collaboration

How a gRPC Request Works

A typical request follows these steps:

Application



Client Stub



Serialize (Protobuf)



HTTP/2

══════════════════════

Server Stub



Deserialize



Business Logic



Database



Response

══════════════════════

Serialize



HTTP/2



Deserialize



Application

Notice that developers never manually serialize data or write HTTP requests.


REST vs gRPC

Feature REST gRPC
Data Format JSON Protocol Buffers
Protocol HTTP/1.1 HTTP/2
Payload Size Larger Smaller
Performance Good Excellent
Streaming Limited Built-in
Code Generation Usually manual Automatic
Type Safety Weak Strong
Browser Support Native Requires gRPC-Web or a proxy

When Should You Use gRPC?

gRPC is an excellent choice for:

  • Microservices
  • Internal APIs
  • Container orchestration
  • Observability platforms
  • AI inference servers
  • Kubernetes operators
  • Distributed systems
  • Real-time streaming applications

REST is often a better choice for:

  • Public APIs
  • Browser-based applications
  • Third-party integrations
  • Simple CRUD services

Many organizations use both: gRPC for internal service-to-service communication and REST for public-facing APIs.


Advantages

  • High performance
  • Small binary payloads
  • Strong type safety
  • Automatic client and server generation
  • Cross-language support
  • Built-in streaming
  • Efficient HTTP/2 communication
  • Easier maintenance through shared schemas

Limitations

gRPC is not the right choice for every project.

Some limitations include:

  • Binary data is not human-readable.
  • Requires code generation.
  • Browser support requires gRPC-Web or a proxy.
  • Harder to inspect with simple HTTP tools compared to JSON APIs.

Conclusion

gRPC and Protocol Buffers have become the backbone of communication in many modern distributed systems. By combining compact binary serialization with HTTP/2 and automatic code generation, they provide a fast, reliable, and strongly typed way for services to interact.

The .proto file acts as the shared contract, defining both the data structures and the available RPC methods. From this single definition, gRPC generates client and server stubs, eliminating repetitive networking code and allowing developers to focus on business logic instead of protocol details.

While REST remains an excellent choice for public APIs and browser-facing applications, gRPC excels in service-to-service communication where performance, scalability, and maintainability matter most. Understanding both technologies enables you to choose the right tool for the right use case and build efficient, modern applications.