Help us improve
Share bugs, ideas, or general feedback.
From dotnet-skills
Choosing inter-service protocols. REST vs gRPC vs SignalR vs SSE decision matrix, tradeoffs.
npx claudepluginhub wshaddix/dotnet-skillsHow this skill is triggered — by the user, by Claude, or both
Slash command
/dotnet-skills:dotnet-service-communicationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Higher-level routing skill for choosing the right service communication protocol. Provides a decision matrix mapping requirements (latency, direction, client type, payload format, browser support) to the five primary .NET communication protocols: gRPC, SignalR, SSE, JSON-RPC 2.0, and REST. Routes to specialized skills for implementation depth.
Building real-time features. SignalR hubs, SSE (.NET 10), JSON-RPC 2.0, gRPC streaming, scaling.
Guides gRPC service development in .NET with proto definitions, C# implementations, server/client setup using Aspire, and gRPC vs REST comparison for microservices.
Provides .NET ecosystem guidance: C#/F# language features, project structure, NuGet package selection, and architecture decisions across ASP.NET Core, Blazor, EF Core, and cloud/desktop/mobile targets.
Share bugs, ideas, or general feedback.
Higher-level routing skill for choosing the right service communication protocol. Provides a decision matrix mapping requirements (latency, direction, client type, payload format, browser support) to the five primary .NET communication protocols: gRPC, SignalR, SSE, JSON-RPC 2.0, and REST. Routes to specialized skills for implementation depth.
Out of scope: HTTP client factory patterns and resilience pipelines -- see [skill:dotnet-http-client] and [skill:dotnet-resilience]. Native AOT architecture and trimming strategies -- see [skill:dotnet-native-aot] for AOT compilation, [skill:dotnet-aot-architecture] for AOT-first design patterns, and [skill:dotnet-trimming] for trim-safe development.
Cross-references: [skill:dotnet-grpc] for gRPC implementation, [skill:dotnet-realtime-communication] for SignalR/SSE/JSON-RPC details, [skill:dotnet-http-client] for REST/HTTP client patterns. See [skill:dotnet-integration-testing] for testing service communication patterns.
Use this matrix to choose the right protocol based on your requirements:
| Requirement | gRPC | SignalR | SSE | JSON-RPC 2.0 | REST |
|---|---|---|---|---|---|
| Direction | All four patterns | Full-duplex | Server-to-client | Request-response | Request-response |
| Wire format | Protobuf (binary) | JSON or MessagePack | Text (JSON lines) | JSON | JSON/XML |
| Browser support | gRPC-Web (proxy needed) | Yes (JS client) | Yes (native EventSource) | Via WebSocket | Yes (fetch/XHR) |
| Contract | .proto schema | Hub interface | Convention | JSON-RPC spec | OpenAPI/Swagger |
| Latency | Lowest | Low | Low | Medium | Medium |
| Throughput | Highest | High | Moderate | Moderate | Moderate |
| Streaming | All 4 patterns | Server + client streaming | Server push only | No | No (chunked transfer) |
| Connection | HTTP/2 persistent | WebSocket (with fallback) | HTTP/1.1+ persistent | Transport-dependent | Per-request |
| Service-to-service | Excellent | Good | Limited | Niche | Good |
| AOT-friendly | Yes (Protobuf) | Yes | Yes | Yes | Yes (with STJ source gen) |
Is this service-to-service (no browser)?
├── Yes → Do you need streaming?
│ ├── Yes → gRPC streaming [skill:dotnet-grpc]
│ └── No → Is it request-response?
│ ├── High throughput / binary → gRPC (unary) [skill:dotnet-grpc]
│ └── Standard CRUD / public API → REST [skill:dotnet-http-client]
└── No (browser client) → Do you need real-time?
├── Yes → Do you need bidirectional?
│ ├── Yes → SignalR [skill:dotnet-realtime-communication]
│ └── No (server push only) → SSE [skill:dotnet-realtime-communication]
└── No → REST [skill:dotnet-http-client]
Special cases:
- LSP / tooling protocol → JSON-RPC 2.0 [skill:dotnet-realtime-communication]
- Mixed (browser + service-to-service) → REST for browser, gRPC for internal
Best for: Service-to-service communication, high-throughput streaming, strongly-typed contracts.
.proto filesWhen NOT to use: Direct browser communication (requires gRPC-Web proxy), simple CRUD APIs consumed by external clients, scenarios where human-readable payloads are required.
See [skill:dotnet-grpc] for full implementation details.
Best for: Browser-facing real-time applications, interactive dashboards, chat, collaborative features.
When NOT to use: Server-to-client-only push (use SSE instead), service-to-service (use gRPC instead), scenarios where the SignalR client library cannot be included.
See [skill:dotnet-realtime-communication] for SignalR patterns and hub implementation.
Best for: Simple server-to-client push notifications, live feeds, status updates.
TypedResults.ServerSentEventsEventSource API -- no client library neededLast-Event-IDWhen NOT to use: Bidirectional communication (use SignalR), high-throughput binary streaming (use gRPC), client-to-server messages needed.
See [skill:dotnet-realtime-communication] for SSE implementation details.
Best for: Tooling protocols (Language Server Protocol), structured RPC over simple transports.
When NOT to use: Real-time streaming (use SignalR or gRPC), high-throughput service-to-service (use gRPC), standard web APIs (use REST).
See [skill:dotnet-realtime-communication] for JSON-RPC 2.0 patterns.
Best for: Public APIs, standard CRUD operations, broad client compatibility.
When NOT to use: Real-time push (use SSE or SignalR), high-throughput service-to-service (use gRPC), bidirectional streaming (use SignalR or gRPC).
See [skill:dotnet-http-client] for HTTP client patterns, resilience, and IHttpClientFactory.
Browser ─── REST/SignalR ──→ API Gateway ──→ gRPC ──→ Internal Services
──→ gRPC ──→ Order Service
──→ gRPC ──→ Inventory Service
Use REST for public-facing APIs and SignalR for real-time browser features. Internal service-to-service communication uses gRPC for performance. The API gateway translates between protocols.
Internal Services ──→ Message Broker ──→ SSE Endpoint ──→ Browser Dashboard
──→ gRPC Stream ──→ Monitoring Service
Internal events flow through a message broker. Browser dashboards consume via SSE. Other services consume via gRPC streaming for higher throughput.
A single ASP.NET Core host can serve both gRPC and REST:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddControllers();
var app = builder.Build();
// gRPC for internal service-to-service
app.MapGrpcService<OrderGrpcService>();
// REST for external clients
app.MapControllers();
// SSE for real-time browser updates
app.MapGet("/events/orders", (OrderEventService svc, CancellationToken ct) =>
TypedResults.ServerSentEvents(svc.GetEventsAsync(ct)));
See [skill:dotnet-native-aot] for AOT compilation pipeline and [skill:dotnet-aot-architecture] for AOT-compatible communication patterns.