06 - Introduction to gRPC

📋 Jump to Takeaways

gRPC is a remote procedure call framework built on top of HTTP/2 and Protocol Buffers. You define a service in a .proto file, generate server and client code, and call remote functions as if they were local. Google open-sourced it in 2015 and uses it for virtually all internal service communication.

What Makes gRPC Different

With REST, you think in resources and HTTP verbs. GET /links/abc123, POST /links, DELETE /links/abc123. You serialize to JSON, send it over HTTP/1.1, and parse it on the other side.

With gRPC, you think in functions. CreateLink(request) returns a response. The framework handles serialization (protobuf), transport (HTTP/2), and code generation. You write the business logic, gRPC handles the plumbing.

HTTP/2

gRPC uses HTTP/2, not HTTP/1.1. This matters because HTTP/2 supports:

  • Multiplexing: multiple requests and responses flow simultaneously over a single TCP connection. In HTTP/1.1, each request blocks the connection until it completes — if you need 5 requests in parallel, you open 5 connections. HTTP/2 splits one connection into independent streams, so all requests are in-flight at once. For gRPC, this means a client can make many concurrent RPC calls without opening multiple connections.
  • Binary framing: HTTP/1.1 is plain text — the parser scans character by character looking for delimiters like \r\n. HTTP/2 splits everything into binary frames with a fixed structure (length, type, flags, stream ID, payload). The parser knows exactly how many bytes to read and which stream they belong to. This makes parsing faster, enables multiplexing (frames from different streams interleave), and fits naturally with protobuf's binary payload.
  • Streams: HTTP/2 supports multiple concurrent streams over a single connection. gRPC uses this for streaming RPCs — the client opens a stream and both sides can send messages on it independently. This is different from HTTP/2 "server push" (which is deprecated in browsers). gRPC streaming is always client-initiated but allows the server to send multiple responses back on the same stream.
  • Header compression: HTTP/1.1 sends headers as plain text on every request — often the same Content-Type, Authorization, User-Agent repeated over and over. HTTP/2 uses HPACK, a compression algorithm that assigns index numbers to common headers and remembers previously seen headers on the connection. After the first request, repeated headers cost almost nothing. For gRPC, where every call sends the same metadata (auth tokens, content type), this saves significant bandwidth.

You don't configure any of this. The gRPC library handles it. But it's good to know why gRPC connections are more efficient than REST over HTTP/1.1.

Four Types of RPC

gRPC supports four communication patterns:

Unary: one request, one response. Like a normal function call.

rpc GetLink(GetLinkRequest) returns (GetLinkResponse);

Server streaming: one request, multiple responses. The server sends a stream of messages.

rpc ListLinks(ListLinksRequest) returns (stream Link);

Client streaming: multiple requests, one response. The client sends a stream, the server responds once.

rpc BatchCreateLinks(stream CreateLinkRequest) returns (BatchCreateLinksResponse);

Bidirectional streaming: both sides send streams simultaneously.

rpc SyncLinks(stream SyncRequest) returns (stream SyncResponse);

We'll cover streaming in detail in later lessons. For now, we'll focus on unary RPCs.

Service Definition

A gRPC service is defined in a .proto file. Here's our link shortener:

syntax = "proto3";

package shortener;

option go_package = "shortener/pb";

message Link {
  int64 id = 1;
  string url = 2;
  string short_code = 3;
  int64 clicks = 4;
}

message CreateLinkRequest {
  string url = 1;
}

message CreateLinkResponse {
  Link link = 1;
}

message GetLinkRequest {
  string short_code = 1;
}

message GetLinkResponse {
  Link link = 1;
}

message DeleteLinkRequest {
  string short_code = 1;
}

message DeleteLinkResponse {}

service LinkService {
  rpc CreateLink(CreateLinkRequest) returns (CreateLinkResponse);
  rpc GetLink(GetLinkRequest) returns (GetLinkResponse);
  rpc DeleteLink(DeleteLinkRequest) returns (DeleteLinkResponse);
}

Each rpc line defines a method. It takes one message type and returns one message type. Even if you don't need a request or response body, you still define empty messages (DeleteLinkResponse {}). This lets you add fields later without breaking the API.

Generated Code

After running protoc with the gRPC plugin, you get:

  1. A server interface to implement:
type LinkServiceServer interface {
    CreateLink(context.Context, *CreateLinkRequest) (*CreateLinkResponse, error)
    GetLink(context.Context, *GetLinkRequest) (*GetLinkResponse, error)
    DeleteLink(context.Context, *DeleteLinkRequest) (*DeleteLinkResponse, error)
    mustEmbedUnimplementedLinkServiceServer()
}
  1. An UnimplementedLinkServiceServer struct whose methods all return "unimplemented" errors. You embed this in your server so you don't have to implement every method at once.
type UnimplementedLinkServiceServer struct{}

func (UnimplementedLinkServiceServer) CreateLink(context.Context, *CreateLinkRequest) (*CreateLinkResponse, error) {
    return nil, status.Errorf(codes.Unimplemented, "method CreateLink not implemented")
}
// ... same for GetLink, DeleteLink, etc.
  1. A client struct with methods that make the RPC calls.
type LinkServiceClient interface {
    CreateLink(ctx context.Context, in *CreateLinkRequest, opts ...grpc.CallOption) (*CreateLinkResponse, error)
    GetLink(ctx context.Context, in *GetLinkRequest, opts ...grpc.CallOption) (*GetLinkResponse, error)
    // ...
}

gRPC vs REST

Use gRPC when:

  • Services talk to services (not browsers)
  • You need streaming
  • You want strict contracts with code generation
  • Performance matters (binary, HTTP/2, multiplexing)

Use REST when:

  • You have a public API that developers call with curl
  • Browsers are the primary client
  • You want human-readable request/response bodies
  • Your team is more comfortable with REST

You can also have both. gRPC-Gateway (lesson 15) lets you expose a gRPC service as a REST API.

Key Takeaways

  • gRPC is an RPC framework built on HTTP/2 and protobuf
  • You define services in .proto files and generate server/client code
  • Four RPC types: unary, server streaming, client streaming, bidirectional
  • HTTP/2 gives you multiplexing, binary framing, and header compression for free
  • Always define request and response messages, even if empty
  • gRPC is for service-to-service communication, REST is for public APIs

💻 Examples

Complete examples for this lesson. Copy and run locally.

📝 Ready to test your knowledge?

Answer the quiz below to mark this lesson complete.

Spot something off? Report an issue

© 2026 ByteLearn.dev. Free courses for developers. · Privacy