.NET microservices with gRPC
The .proto contract, single source of truth
.proto file: it describes the messages and the service, independent of any language. This is the contract — neither client nor server writes it by hand. You declare a service Pricing exposing an rpc GetQuote (QuoteRequest) call that returns a QuoteReply , with every field numbered ( string sku = 1; , int32 quantity = 2; ) — those numbers are the key to backward compatibility: you never reuse one.
.csproj via <Protobuf Include="pricing.proto" /> . The Grpc.Tools package then generates, at compile time, the server base class and the typed client — no DTOs to copy by hand:
Typed server and client
Pricing.PricingBase class and overrides the method. No routing to wire, no manual deserialization: you receive a strongly typed message.
HttpClient either. You inject the generated client via AddGrpcClient , and call it like a local method:
Streaming, the deciding argument
stream pushes results as they come; a bidirectional stream opens a full-duplex channel ideal for telemetry or chat. You write into an IServerStreamWriter<T> and the client iterates with await foreach — no polling, no hand-rolled WebSocket.
gRPC versus REST: choosing with eyes open
The healthy reflex: REST on the public façade, gRPC on the inside . The .proto contract then becomes the formal boundary between your services — versioned, shared, and checked by the compiler.