# Golang Grpc

> Build, review, or debug Go gRPC services and clients using `google.golang.org/grpc`. Use for protobuf evolution, interceptors, status errors, metadata, streaming, credentials, deadlines, graceful shutdown, and transport-level tests.

- Skill: `reagin/golang-grpc` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add reagin/golang-grpc`
- Raw SKILL.md: https://api.skillmd.com/api/skills/reagin/golang-grpc/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: reagin (https://skillmd.com/u/reagin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/reagin/golang-grpc

---


# Go gRPC services and clients

Preserve the project's protobuf layout, compatibility policy, generation toolchain, and transport conventions. Use its existing generator versions and limit regeneration to affected APIs.

## Inspect before changing

Locate:

- `go.mod`, `.proto` sources, Buf/protoc configuration, and generated-file policy;
- server and client construction, credentials, interceptors, limits, health checks, and reflection policy;
- status-code mapping, metadata propagation, streaming ownership, and shutdown behavior;
- compatibility checks and transport-level tests.

Use API details supported by the selected module versions. Prefer the repository's existing `buf` or `protoc` command rather than inventing another generation path.

For concrete server/client APIs, status mapping, metadata, streaming, and graceful shutdown, read [runtime recipes](references/runtime-recipes.md). For an in-memory transport test that exercises protobuf encoding and interceptors, read [bufconn testing](references/bufconn-testing.md).

## Protobuf evolution

- Treat field numbers and wire types as compatibility-sensitive. Do not reuse removed field numbers or names; reserve them where the project's policy requires it.
- Keep package names and `go_package` stable unless a migration is intentional.
- Use request and response messages so an RPC can evolve without changing its method shape. Reuse `google.protobuf.Empty` only when the project's compatibility policy accepts that constraint.
- Preserve unknown-field and enum behavior expected by mixed-version clients and servers.
- Run the repository's lint or breaking-change check when available; compilation alone does not prove wire compatibility.

Never hand-edit generated protobuf or gRPC files.

## Transport boundaries

Map expected domain failures to intentional gRPC status codes and keep unexpected internal details out of client-visible messages. A raw Go error generally becomes `codes.Unknown`; do not leak it merely to avoid writing a mapping. Preserve error details only when their protobuf contract is safe and stable for clients.

Use `status.Code` or `status.FromError` on the client instead of parsing messages. Distinguish `Unauthenticated` from `PermissionDenied`, and use `Canceled` or `DeadlineExceeded` consistently with the context result. Attach typed details with `WithDetails` only when clients can depend on that protobuf contract.

Propagate caller contexts. Give bounded unary calls and finite operations an appropriate deadline at the owning boundary; do not impose a short generic timeout on intentionally long-lived streams. Retry only operations whose status, idempotency, backoff, and retry budget make replay safe.

For streaming RPCs, define which side owns sending, receiving, and closure. Ensure cancellation unblocks goroutines, handle `io.EOF` distinctly from failures, and avoid concurrent sends on a stream unless the selected API explicitly permits them.

## Security and resource controls

Authenticate and protect transport across the actual trust boundary. TLS or mTLS is common across networks; plaintext credentials can be acceptable only when another verified layer terminates transport security or the channel is explicitly local and trusted. Do not assume service-mesh presence makes application authorization unnecessary.

Enforce authorization against the full RPC method and relevant resource, not merely a valid token. Bound inbound and outbound message sizes, concurrent streams, metadata, connection age, and handler work where untrusted peers can consume resources. Configure keepalive defensively and compatibly on both ends.

Reflection is an operational policy, not a security boundary. Enable or restrict it according to the deployment's debugging and exposure needs; authorization and resource controls must remain correct either way.

## Lifecycle

Register health state consistently with readiness and shutdown. During shutdown, stop accepting new work, mark the service unavailable when appropriate, allow in-flight RPCs a bounded drain period, and use the project's forced-stop fallback if graceful shutdown cannot complete.

## Verification

Regenerate only affected outputs, format, compile, and run relevant tests. Use direct handler tests for domain mapping and `bufconn` or loopback transport when serialization, metadata, interceptors, streaming, or status codes matter. Verify cancellation, deadline, malformed input, authorization, message-limit, compatibility, and shutdown paths introduced by the change.

## Official references

- [gRPC-Go documentation](https://pkg.go.dev/google.golang.org/grpc)
- [gRPC authentication guide](https://grpc.io/docs/guides/auth/)
- [gRPC status codes](https://grpc.io/docs/guides/status-codes/)
- [Protocol Buffers updating rules](https://protobuf.dev/programming-guides/proto3/#updating)
- [Buf breaking-change detection](https://buf.build/docs/breaking/)

