gRPC & Protobuf Fundamentals
Define service contracts in .proto files, generate C# code with Grpc.Tools, and understand gRPC transport.
gRPC & Protobuf Fundamentals is a free C# Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is gRPC?
gRPC is a high-performance, language-agnostic RPC framework developed by Google. It uses HTTP/2 for transport and Protocol Buffers (Protobuf) as the serialization format — much faster and more compact than JSON over HTTP/1.1.
Protocol Buffers: The IDL
You define your service contract in a .proto file. Protobuf IDL (Interface Definition Language) is strongly typed and language-neutral — the same file generates client/server code in C#, Go, Python, etc.
// greet.proto
syntax = "proto3";
option csharp_namespace = "GrpcService";
package greet;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}Setting Up a gRPC Server in .NET
Create a gRPC project with dotnet new grpc. Add .proto files to the project and Grpc.Tools generates the C# classes automatically at build time.
// .csproj snippet
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
// Program.cs
builder.Services.AddGrpc();
var app = builder.Build();
app.MapGrpcService<GreeterService>();
app.Run();Implementing a gRPC Service
Inherit from the generated base class and override the RPC method. The framework handles serialization, HTTP/2 framing, and routing automatically.
using Grpc.Core;
using GrpcService;
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger) => _logger = logger;
public override Task<HelloReply> SayHello(
HelloRequest request,
ServerCallContext context)
{
_logger.LogInformation("Saying hello to {Name}", request.Name);
return Task.FromResult(new HelloReply
{
Message = $"Hello, {request.Name}!"
});
}
}Creating a gRPC Client
The Protobuf compiler also generates a strongly typed client class. Use GrpcChannel to connect and call the service as if it were a local method.
// Client project: add Grpc.Net.Client package
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "Alice" });
Console.WriteLine(reply.Message); // Hello, Alice!Protobuf Types and Field Numbers
Each field in a Protobuf message has a unique field number (1–536870911). Field numbers are encoded in the binary format — never change them once deployed or you break backward compatibility.
message Product {
int32 id = 1;
string name = 2;
double price = 3;
int32 stock = 4;
bool is_active = 5;
repeated string tags = 6; // array
}
// Supported scalar types:
// int32, int64, uint32, uint64, float, double
// bool, string, bytes, enumEnums and Nested Messages
Protobuf supports enums and nested message types. Use them to model complex domain objects in your service contract.
enum OrderStatus {
ORDER_STATUS_UNSPECIFIED = 0;
ORDER_STATUS_PENDING = 1;
ORDER_STATUS_SHIPPED = 2;
ORDER_STATUS_CANCELLED = 3;
}
message Order {
int32 id = 1;
OrderStatus status = 2;
repeated OrderLine lines = 3;
}
message OrderLine {
int32 product_id = 1;
int32 quantity = 2;
double price = 3;
}HTTP/2 and gRPC Transport
gRPC uses HTTP/2 which supports multiplexing — multiple concurrent RPC calls on a single TCP connection — reducing latency and connection overhead compared to HTTP/1.1.
// gRPC requires HTTP/2
// For local dev with HTTP (not HTTPS), enable HTTP/2 cleartext:
builder.WebHost.ConfigureKestrel(opt =>
opt.ListenLocalhost(5000, o => o.Protocols = HttpProtocols.Http2));
// Client for cleartext (dev only)
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
using var channel = GrpcChannel.ForAddress("http://localhost:5000");Error Handling with StatusCode
gRPC uses its own status codes (different from HTTP). Throw RpcException with a Status to send typed error responses to clients.
public override Task<ProductReply> GetProduct(
ProductRequest request,
ServerCallContext context)
{
var product = _repo.FindById(request.Id);
if (product is null)
throw new RpcException(
new Status(StatusCode.NotFound, $"Product {request.Id} not found"));
return Task.FromResult(MapToReply(product));
}gRPC Reflection for Development
Enable gRPC reflection so tools like grpcurl and Postman can discover your services without accessing the .proto file directly.
// dotnet add package Grpc.AspNetCore.Server.Reflection
builder.Services.AddGrpcReflection();
if (app.Environment.IsDevelopment())
app.MapGrpcReflectionService();
// Now use grpcurl:
// grpcurl -plaintext localhost:5000 list
// grpcurl -plaintext localhost:5000 greet.Greeter/SayHelloReal-World: Microservice Product Lookup
A product service exposing a gRPC endpoint used internally by an order service — a classic inter-service communication pattern.
// product.proto
service ProductService {
rpc GetProduct (GetProductRequest) returns (ProductResponse);
rpc ListProducts (ListProductsRequest) returns (ListProductsResponse);
}
// Order service calls it:
public class OrderService
{
private readonly ProductService.ProductServiceClient _products;
public OrderService(ProductService.ProductServiceClient p) => _products = p;
public async Task<Order> PlaceOrderAsync(int productId, int qty)
{
var product = await _products.GetProductAsync(
new GetProductRequest { Id = productId });
return new Order { ProductName = product.Name, Quantity = qty };
}
}Quick Check
Why should you never change an existing Protobuf field number after deployment?
Recap: gRPC & Protobuf Fundamentals
Key takeaways:
- gRPC uses HTTP/2 + Protobuf for fast, strongly typed inter-service communication
- Define service contracts in
.protofiles — code generated at build time - Field numbers are the wire encoding — never change or reuse them
- Inherit from the generated base class and override RPC methods
- Use RpcException with StatusCode for typed error responses
- Enable gRPC reflection for tooling support in development
Frequently asked questions
Is the “gRPC & Protobuf Fundamentals” lesson free?
Yes — the full text of “gRPC & Protobuf Fundamentals” is free to read here on the web, and the C# Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.
What will I learn in “gRPC & Protobuf Fundamentals”?
Define service contracts in .proto files, generate C# code with Grpc.Tools, and understand gRPC transport. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C# Academy?
No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “gRPC & Protobuf Fundamentals” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C# Academy lesson?
Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- gRPC & Protobuf Fundamentals
- Unary & Server Streaming RPCs
- Client & Bidirectional Streaming
- Deadlines, Cancellation & Interceptors