{
"$type": "site.standard.document",
"canonicalUrl": "https://rednafi.com/shards/2026/03/etcd-codebase/",
"description": "Why the etcd codebase is my go-to reference for building gRPC services in Go.",
"path": "/shards/2026/03/etcd-codebase/",
"publishedAt": "2026-03-14T00:00:00.000Z",
"site": "at://did:plc:fgtm2c26vfcj74rfmeggbyqj/site.standard.publication/3mnl6f7ob462z",
"tags": [
"Go",
"gRPC",
"Distributed Systems"
],
"textContent": "I've been writing a lot of Go gRPC services these days at work - database proxies, metadata\nservices, storage orchestration control plane, etc. They require me to go a bit deeper into\nprotobuf and Go gRPC tooling than you'd typically need to. So I started poking around OSS\ngRPC codebases to pick up conventions.\n\nI was mainly looking for pointers on how to organize protobuf definitions, wire up\nserver-side metrics and interceptors, and build ergonomic client wrappers. The default\nanswer here is often \"_go read the Docker or Kubernetes codebase._\" But both of those are\npretty huge and take forever to get accustomed to.\n\nThen I found [etcd]. It's used by Kubernetes' control plane for storing configs in a\nconsistent manner. It exposes a small set of well-defined gRPC endpoints to interact with\nthe storage layer. The core services are defined in a single [rpc.proto] file:\n\nThe full file also defines Watch, Lease, Cluster, Maintenance, and Auth services.\nGrokking that file and the surrounding [api directory] is a good way to learn how to\norganize your protobufs and [generated code]. Some other things I picked up:\n\n- Proto definitions live under [api/], separated into subpackages like etcdserverpb,\n mvccpb, authpb. Generated Go code lives alongside the proto files.\n\n- The RPC handler implementations live under [server/etcdserver/api/v3rpc]. [key.go]\n implements the KV service (Range, Put, DeleteRange, Txn, Compact), and the other services\n follow the same pattern in watch.go, lease.go, member.go, maintenance.go,\n auth.go.\n\n- [grpc.go] shows how to assemble a gRPC server with chained unary and stream interceptors\n using [go-grpc-middleware].\n\n- Server-side Prometheus metrics are wired in [grpc.go] via grpc_prometheus.ServerMetrics\n interceptors. It optionally enables latency histograms when the metric type is\n extensive.\n\n- [metrics.go] defines custom Prometheus counters and histograms on top of the standard gRPC\n ones, things like etcd_network_client_grpc_sent_bytes_total and watch stream durations.\n\n- [interceptor.go] handles logging. newLogUnaryInterceptor logs request/response sizes at\n warn level when latency exceeds a threshold.\n\n- The client has no built-in metrics. The [clientv3 README] says you can wire up\n [go-grpc-prometheus] yourself, but the library doesn't do it for you.\n\n- [retry_interceptor.go] implements client-side retry with backoff, safe retry\n classification for read-only vs mutation RPCs, and auth token refresh on failure.\n\n- The [clientv3 package] wraps the generated gRPC client behind a nicer Go API. I wrote\n about [wrapping a gRPC client in Go] using a similar approach.\n\n- If you're a distributed systems nerd, etcd uses [Raft] for consensus. That part of the\n codebase is its own rabbit hole.\n\nThis has become my go-to whenever I'm wiring up another gRPC service at work. I've gotten\ncomfortable enough with it over the last few weeks that I can point people to specific files\nwhen we need to make decisions.\n\n\n\n\n[etcd]:\n https://github.com/etcd-io/etcd\n\n[rpc.proto]:\n https://github.com/etcd-io/etcd/blob/main/api/etcdserverpb/rpc.proto\n\n[api directory]:\n https://github.com/etcd-io/etcd/tree/main/api\n\n[api/]:\n https://github.com/etcd-io/etcd/tree/main/api\n\n[generated code]:\n https://github.com/etcd-io/etcd/blob/main/api/etcdserverpb/rpc.pb.go\n\n[grpc.go]:\n https://github.com/etcd-io/etcd/blob/main/server/etcdserver/api/v3rpc/grpc.go\n\n[go-grpc-middleware]:\n https://github.com/grpc-ecosystem/go-grpc-middleware\n\n[metrics.go]:\n https://github.com/etcd-io/etcd/blob/main/server/etcdserver/api/v3rpc/metrics.go\n\n[interceptor.go]:\n https://github.com/etcd-io/etcd/blob/main/server/etcdserver/api/v3rpc/interceptor.go\n\n[retry_interceptor.go]:\n https://github.com/etcd-io/etcd/blob/main/client/v3/retry_interceptor.go\n\n[clientv3 package]:\n https://github.com/etcd-io/etcd/tree/main/client/v3\n\n[clientv3 README]:\n https://github.com/etcd-io/etcd/blob/main/client/v3/README.md\n\n[go-grpc-prometheus]:\n https://github.com/grpc-ecosystem/go-grpc-prometheus\n\n[Raft]:\n https://github.com/etcd-io/raft\n\n[server/etcdserver/api/v3rpc]:\n https://github.com/etcd-io/etcd/tree/main/server/etcdserver/api/v3rpc\n\n[key.go]:\n https://github.com/etcd-io/etcd/blob/main/server/etcdserver/api/v3rpc/key.go\n\n[wrapping a gRPC client in Go]:\n /go/wrap-grpc-client/",
"title": "In praise of the etcd codebase"
}