Skip to main content

How to Build a gRPC Service

Define a gRPC service in Protocol Buffers, generate server and client code, implement unary and server-streaming methods, and call the service with deadlines and interceptors.

Difficulty
Intermediate
Duration
50 minutes
Steps
6

What and why

gRPC is a high-performance RPC framework using Protocol Buffers for a compact binary contract and HTTP/2 for multiplexed, streaming transport. It suits internal service-to-service communication where low latency and strong typing matter more than browser friendliness.

Prerequisites

  • Go or Node.js installed.
  • protoc or buf for code generation.
  • Basic understanding of RPC.

Steps

1. Define the service in protobuf

syntax = "proto3";
package orders.v1;

service OrderService {
  rpc GetOrder(GetOrderRequest) returns (Order);
  rpc WatchOrders(WatchRequest) returns (stream Order);
}
message GetOrderRequest { string id = 1; }
message WatchRequest { string customer_id = 1; }
message Order { string id = 1; string status = 2; }

2. Generate code

With buf:

buf generate

Or protoc directly to generate stubs for your language. This produces typed server interfaces and client stubs.

3. Implement the server

Go example for the unary method:

func (s *server) GetOrder(ctx context.Context, req *pb.GetOrderRequest) (*pb.Order, error) {
    o, err := s.store.Find(req.Id)
    if err != nil {
        return nil, status.Error(codes.NotFound, "order not found")
    }
    return &pb.Order{Id: o.ID, Status: o.Status}, nil
}

4. Add a streaming method

Server streaming sends many messages on one call:

func (s *server) WatchOrders(req *pb.WatchRequest, stream pb.OrderService_WatchOrdersServer) error {
    for o := range s.updates(req.CustomerId) {
        if err := stream.Send(o); err != nil { return err }
    }
    return nil
}

5. Call from a client

conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
client := pb.NewOrderServiceClient(conn)
order, _ := client.GetOrder(ctx, &pb.GetOrderRequest{Id: "42"})

6. Add interceptors and deadlines

Use interceptors for cross-cutting concerns (auth, logging, metrics) and always set a deadline on client calls with context.WithTimeout so slow servers cannot hang callers.

Verification

  • Code generation produces server and client stubs.
  • A unary call returns the expected message.
  • A streaming call delivers multiple messages.
  • A call past its deadline returns DeadlineExceeded.

Next Steps

Secure the channel with TLS or mTLS, add a gRPC health check service, expose a gRPC-Web or REST gateway for browser clients, and load-test with proper connection reuse since gRPC multiplexes over a single connection.

Prerequisites

  • Go or Node.js installed
  • protoc or buf installed
  • Basic understanding of RPC

Steps

  • 1
    Define the service in protobuf
  • 2
    Generate code
  • 3
    Implement the server
  • 4
    Add a streaming method
  • 5
    Call from a client
  • 6
    Add interceptors and deadlines

Category

API Design