Build high-performance gRPC services with Protocol Buffers — service definitions, unary and streaming RPCs, interceptors, error handling, and Node.js/Go implementations
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Build high-performance gRPC services with Protocol Buffers — service definitions, unary and streaming RPCs, interceptors, error handling, and Node.js/Go implementations
["Service interface and method definitions","Language/runtime (Node.js, Go, Rust, Python)","Communication pattern (unary, server-streaming, client-streaming, bidirectional)","Authentication and authorization requirements","Deployment target (Kubernetes, Cloud Run, bare metal)"]
outputs
["Proto file definitions with message and service schemas","Server implementation with interceptors","Client stubs with retry and deadline configuration","Streaming handler implementations","Error handling with gRPC status codes","Build configuration for proto compilation"]
gRPC is a high-performance RPC framework using Protocol Buffers for serialization and HTTP/2 for transport. It provides strongly-typed service contracts, automatic code generation, bidirectional streaming, and efficient binary serialization — making it the standard for service-to-service communication in microservice architectures. This skill covers proto file design, server/client implementation in Node.js and Go, streaming patterns, and production hardening.
Key Concepts
gRPC vs. REST
Aspect
gRPC
REST (JSON)
Serialization
Protobuf (binary, ~10x smaller)
JSON (text)
Transport
HTTP/2 (multiplexed)
HTTP/1.1 or HTTP/2
Contract
.proto file (strict)
OpenAPI/informal
Streaming
Native (4 patterns)
Workarounds (SSE, WebSocket)
Code generation
Built-in for 11+ languages
Optional (openapi-generator)
Browser support
Via grpc-web or Connect
Native
Debugging
Needs tooling (grpcurl, Evans)
curl, browser
Four Communication Patterns
1. UNARY (request-response):
Client ──request──→ Server
Client ←──response── Server
2. SERVER STREAMING:
Client ──request──→ Server
Client ←──stream──── Server (multiple responses)
3. CLIENT STREAMING:
Client ──stream──→ Server (multiple requests)
Client ←──response── Server
4. BIDIRECTIONAL STREAMING:
Client ←──stream──→ Server (both directions)
# buf.gen.yamlversion:v2plugins:# Go-remote:buf.build/protocolbuffers/goout:gen/goopt:paths=source_relative-remote:buf.build/grpc/goout:gen/goopt:paths=source_relative# TypeScript (connect-es for modern TS)-remote:buf.build/connectrpc/esout:gen/tsopt:target=ts-remote:buf.build/bufbuild/esout:gen/tsopt:target=ts
# Generate code
buf generate
# Lint proto files
buf lint
# Check for breaking changes against main branch
buf breaking --against '.git#branch=main'
Best Practices
Always set deadlines on client calls. A missing deadline means a stuck RPC can hold resources indefinitely. Default to 5-30 seconds depending on the operation.
Use buf for proto management. It handles linting, breaking change detection, and multi-language code generation in a single tool.
Design proto messages for forward compatibility. Never reuse field numbers. Mark removed fields as reserved. Add new fields with new numbers.
Use interceptors for cross-cutting concerns. Logging, auth, rate limiting, tracing, and metrics belong in interceptors, not service methods.
Prefer server streaming over polling. If clients repeatedly call an RPC to check for changes, a server-streaming RPC is more efficient.
Use connect-rpc for browser clients instead of grpc-web. Connect supports gRPC, gRPC-web, and a simpler HTTP-based protocol, with first-class TypeScript support.
Common Pitfalls
Pitfall
Symptom
Fix
No deadline set
Stuck RPCs consume connections forever
Always pass a deadline; use interceptor to enforce default
Using int64 without longs: String
Precision loss in JavaScript (numbers > 2^53)
Configure proto-loader with longs: String or use BigInt
Proto field number reuse
Silent data corruption after field removal
Use reserved for removed fields; never reuse numbers
No health check endpoint
Load balancer cannot determine service readiness
Implement gRPC health checking protocol (grpc.health.v1.Health)
Streaming without backpressure
Memory exhaustion on fast producer / slow consumer
Check stream.Write return value in Go; use flow control
Large messages without limit
OOM on unexpected payload
Set grpc.max_receive_message_length (default 4MB)
Missing TLS in production
Plaintext credentials on the wire
Use grpc.credentials.createSsl() or mTLS for service-to-service
Not handling UNAVAILABLE with retry
Transient failures cause user-visible errors
Configure retry policy or use client-side retry interceptor for idempotent RPCs