gRPC vs REST in .NET — When to Use Which cover image

gRPC vs REST in .NET — When to Use Which

By Julian Krause · Sunday, February 1, 2026 · ~3 min read

The gRPC vs REST debate often generates more heat than light. Both are excellent tools for different situations. After running both in production across multiple .NET services, here is a practical guide for choosing between them.

REST — The Default for Public APIs

REST over HTTP/JSON is the universal standard. Every language, every platform, every tool understands it. For public APIs consumed by external developers, REST is the right choice. The discoverability, cacheability, and tooling ecosystem are unmatched.

// ASP.NET Core Minimal API — clean, simple, universal
app.MapGet("/api/orders/{id:guid}", async (Guid id, AppDbContext db) =>
{
    var order = await db.Orders
        .AsNoTracking()
        .Where(o => o.PublicId == id)
        .Select(o => new OrderResponse(o.PublicId, o.Status.ToString(), o.TotalAmount))
        .FirstOrDefaultAsync();

    return order is not null ? Results.Ok(order) : Results.NotFound();
});

app.MapPost("/api/orders", async (CreateOrderRequest request, ISender sender) =>
{
    var result = await sender.Send(new CreateOrderCommand(request.CustomerId, request.Items));
    return Results.Created($"/api/orders/{result.OrderId}", result);
});

gRPC — The Choice for Service-to-Service Communication

Where gRPC excels is internal service-to-service communication. Binary serialization with Protocol Buffers is significantly faster than JSON. Strongly-typed contracts prevent drift between services. HTTP/2 multiplexing eliminates head-of-line blocking. Streaming support enables patterns that REST cannot match.

// order_service.proto
syntax = "proto3";
option csharp_namespace = "OrderService.Grpc";

service OrderService {
  rpc GetOrder (GetOrderRequest) returns (OrderResponse);
  rpc CreateOrder (CreateOrderRequest) returns (CreateOrderResponse);
  rpc StreamOrderUpdates (StreamOrdersRequest) returns (stream OrderUpdate);
}

message GetOrderRequest {
  string order_id = 1;
}

message OrderResponse {
  string order_id = 1;
  string status = 2;
  double total_amount = 3;
}
// gRPC service implementation in .NET
public class OrderGrpcService(AppDbContext db) : OrderService.OrderServiceBase
{
    public override async Task<OrderResponse> GetOrder(
        GetOrderRequest request, ServerCallContext context)
    {
        var orderId = Guid.Parse(request.OrderId);
        var order = await db.Orders
            .AsNoTracking()
            .FirstOrDefaultAsync(o => o.PublicId == orderId, context.CancellationToken)
            ?? throw new RpcException(new Status(StatusCode.NotFound, "Order not found"));

        return new OrderResponse
        {
            OrderId = order.PublicId.ToString(),
            Status = order.Status.ToString(),
            TotalAmount = (double)order.TotalAmount
        };
    }
}

Performance Comparison

In our benchmarks, gRPC was consistently 5-8x faster than REST/JSON for small payloads and up to 15x faster for large payloads. The difference comes from binary serialization (Protocol Buffers vs JSON), HTTP/2 multiplexing, and header compression.

However, raw performance is rarely the deciding factor. If your REST API responds in 5ms, making it respond in 0.5ms with gRPC does not change the user experience. Performance matters when you have thousands of inter-service calls per second, where the cumulative overhead adds up.

The Hybrid Approach

In practice, most systems benefit from using both. REST for external APIs and browser-facing endpoints. gRPC for internal service-to-service communication where performance and type safety matter most.

var builder = WebApplication.CreateBuilder(args);

// Both in the same application
builder.Services.AddGrpc();
builder.Services.AddControllers();

var app = builder.Build();

app.MapGrpcService<OrderGrpcService>();   // Internal gRPC
app.MapControllers();                      // External REST

app.Run();

The decision framework is simple: if the consumer is a browser, mobile app, or third-party developer, use REST. If the consumer is another service you control, consider gRPC. If you are unsure, start with REST — you can always add gRPC later for the hot paths.


Comments (2)

Anna Thursday, February 19, 2026 5:08 PM

Great post! I learned a lot from this.

Clara Thursday, February 19, 2026 8:08 PM

Interesting thought, thanks for adding that.

Ben Friday, February 20, 2026 5:08 PM

Interesting perspective, I hadn't thought of it that way.

Leave a Comment