Architecture: consistency and evolution · 3 MIN READ
gRPC and Protobuf: generated methods still need an operational contract
Define deadlines, stream ownership, status mapping and compatible message evolution.
Generated Go stubs remove repetitive transport code, not the need to design a distributed operation. A gRPC method can block, partially stream data, be retried or outlive its caller unless the application defines its lifetime. Treat protobuf fields as a versioned wire contract and the RPC method as a budgeted operation with explicit authorization and failure semantics.
system-design · A MAP OF THE IDEA
- Version wire contract
- Verify identity + budget
- Bound stream ownership
- Map outcomes + resume
Useful when
- Define deadlines, stream ownership, status mapping and compatible message evolution.
- Makes the owner and the failure boundary explicit.
Watch out
- Do not reuse removed protobuf field numbers; reserve them and keep old message fixtures.
- Run native service and failure tests in your own development environment.
Implementation & operation cost: Additional state and tests must be justified by the demonstrated failure; this lesson is not a requirement for every Go program.
The contract and the failure
Generated Go stubs remove repetitive transport code, not the need to design a distributed operation. A gRPC method can block, partially stream data, be retried or outlive its caller unless the application defines its lifetime. Treat protobuf fields as a versioned wire contract and the RPC method as a budgeted operation with explicit authorization and failure semantics.
Work through the example
Set or propagate deadlines because an RPC has no useful universal business timeout. Bound stream queues, use backpressure and make one goroutine own each send/receive direction according to the API contract. Verify metadata-based identity at the server rather than treating all metadata as trusted. Pin protoc and its Go plugins so generated code can be reproduced.
package main
import (
"context"
"fmt"
"time"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func classify(ctx context.Context) error {
if err := ctx.Err(); err != nil {
return status.FromContextError(err).Err()
}
return nil
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
cancel()
err := classify(ctx)
fmt.Println(status.Code(err) == codes.Canceled) // true, not DeadlineExceeded
}The cancelled context maps to the protocol’s cancellation status. It is not rewritten as a successful empty result or confused with expiration of a deadline. In a real handler, domain errors need a deliberate status mapping that does not reveal internal credentials or SQL text; the client separately decides whether a retry is semantically safe.
Production decisions
Do not reuse removed protobuf field numbers; reserve them and keep old message fixtures. A cancelled stream can already have produced durable effects or partial results. Retrying a stream or RPC requires an application identity and a resume/deduplication policy. Test old/new clients, missing deadlines, a slow peer, mid-stream failure and shutdown. Native gRPC networking is taught here, not added to the iOS guest runtime.
Explain it in an interview
A streaming RPC was cancelled after several replies. Can its entire operation be assumed to have had no effects? No. Define partial-result, durable-effect and resume/idempotency semantics; deadlines and generated types do not provide atomic rollback. Describe the state before the operation, its owner, the failure between steps and the evidence you would test. Distinguish what this example demonstrates from the infrastructure a production service still needs.
TAKE THIS WITH YOU
Define deadlines, stream ownership, status mapping and compatible message evolution. No. Define partial-result, durable-effect and resume/idempotency semantics; deadlines and generated types do not provide atomic rollback.
Check your understanding
A streaming RPC was cancelled after several replies. Can its entire operation be assumed to have had no effects?
Go to the source
Progress stays in this browser. No account needed.