Microservices in Go

gRPC, service communication, health checks, and production patterns.

Advanced 40 min read 🐹 Go

Why Go for Microservices?

Fast startup

Compiled binary starts in milliseconds. No JVM warmup, no interpreter.

Low memory

A Go microservice uses 10-50MB. A Java equivalent uses 200-500MB.

Single binary

Deploy one file. No runtime dependencies, no package managers.

Built-in concurrency

Handle thousands of concurrent requests with goroutines.

gRPC

// user.proto
syntax = "proto3";
package user;

service UserService {
    rpc GetUser(GetUserRequest) returns (User);
    rpc ListUsers(ListUsersRequest) returns (stream User);
}

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

Docker Multi-Stage Build

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server

FROM scratch
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]

Final image: ~10MB (vs 200MB+ for a typical Node.js or Java image). The scratch base image contains nothing — just your binary.

Key Takeaway: Go's single-binary deployment + tiny Docker images + fast startup make it ideal for microservices and Kubernetes. Use gRPC for internal service communication, HTTP/JSON for external APIs.
gRPC Communication
Client
Go/Python/Java
Protobuf
serialize
HTTP/2
transport
Server
Go service
Response
protobuf

Practice Exercises

Hard Production Scenario

Design a solution using these concepts for a real-world production system.

Hard Performance Analysis

Benchmark two different approaches and explain which is better and why.