dotnet-cqrs/docs/getting-started/06-choosing-http-or-grpc.md

439 lines
10 KiB
Markdown

# Choosing HTTP vs gRPC
Understand when to use HTTP, gRPC, or both protocols for your application.
## Quick Decision Guide
| Scenario | Recommendation |
|----------|---------------|
| Public API | ✅ HTTP |
| Web browser clients | ✅ HTTP |
| Mobile apps (REST) | ✅ HTTP |
| Microservices (internal) | ✅ gRPC |
| High-performance APIs | ✅ gRPC |
| Low-latency requirements | ✅ gRPC |
| Need both internal & public | ✅ Both (Dual Protocol) |
| Existing REST clients | ✅ HTTP |
| .NET-to-.NET communication | ✅ gRPC |
## HTTP (Minimal API)
### What It Is
HTTP integration uses ASP.NET Core Minimal API to expose commands and queries as REST endpoints.
### When to Use
**Best for:**
- Public APIs
- Web browser clients (JavaScript, React, Vue, etc.)
- Mobile apps expecting REST
- Third-party integrations
- Developer-friendly exploration (Swagger)
- Simple authentication (API keys, JWT)
### Pros
-**Universal compatibility** - Works everywhere (browsers, curl, Postman)
-**Human-readable** - JSON payloads are easy to debug
-**Swagger/OpenAPI** - Automatic API documentation
-**Caching** - HTTP caching headers work out of the box
-**Familiar** - Developers know REST
-**Tooling** - Excellent debugging and testing tools
### Cons
-**Lower performance** - Text-based JSON vs binary Protocol Buffers
-**Larger payloads** - JSON is verbose compared to binary
-**No streaming** - Single request-response (without SSE/WebSockets)
-**Manual client code** - No automatic client generation
### Example Setup
```csharp
var builder = WebApplication.CreateBuilder(args);
// Register CQRS
builder.Services.AddSvrntyCQRS();
builder.Services.AddDefaultCommandDiscovery();
builder.Services.AddDefaultQueryDiscovery();
// Register handlers
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
builder.Services.AddQuery<GetUserQuery, UserDto, GetUserQueryHandler>();
// Add Swagger (optional)
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Map HTTP endpoints
app.UseSvrntyCqrs();
// Enable Swagger
app.UseSwagger();
app.UseSwaggerUI();
app.Run();
```
### Usage
```bash
# Commands (POST only)
curl -X POST http://localhost:5000/api/command/createUser \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"alice@example.com"}'
# Queries (GET or POST)
curl "http://localhost:5000/api/query/getUser?userId=1"
curl -X POST http://localhost:5000/api/query/getUser \
-H "Content-Type: application/json" \
-d '{"userId":1}'
```
## gRPC
### What It Is
gRPC integration uses Protocol Buffers and HTTP/2 for high-performance, strongly-typed communication.
### When to Use
**Best for:**
- Microservices (service-to-service)
- Internal APIs
- High-performance requirements
- Low-latency communication
- Strongly-typed contracts
- .NET-to-.NET or polyglot services
### Pros
-**High performance** - Binary protocol, HTTP/2 multiplexing
-**Compact payloads** - Protocol Buffers are smaller than JSON
-**Strong typing** - Compile-time type safety
-**Code generation** - Automatic client generation
-**Streaming** - Bidirectional streaming support
-**Rich error model** - Structured error details
### Cons
-**Browser support limited** - Requires gRPC-Web proxy
-**Learning curve** - .proto files, Protocol Buffers
-**Less human-readable** - Binary format
-**Tooling** - Fewer debugging tools than REST
-**Firewall issues** - HTTP/2 may be blocked
### Example Setup
```csharp
var builder = WebApplication.CreateBuilder(args);
// Register CQRS
builder.Services.AddSvrntyCQRS();
builder.Services.AddDefaultCommandDiscovery();
builder.Services.AddDefaultQueryDiscovery();
// Register handlers
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
builder.Services.AddQuery<GetUserQuery, UserDto, GetUserQueryHandler>();
// Add gRPC
builder.Services.AddGrpc();
var app = builder.Build();
// Map gRPC services (auto-generated by source generators)
app.MapGrpcService<CommandServiceImpl>();
app.MapGrpcService<QueryServiceImpl>();
// Enable gRPC reflection (for tools like grpcurl)
app.MapGrpcReflectionService();
app.Run();
```
### Proto File
Create `Protos/cqrs_services.proto`:
```protobuf
syntax = "proto3";
option csharp_namespace = "MyApp.Grpc";
service CommandService {
rpc CreateUser (CreateUserRequest) returns (CreateUserResponse);
}
service QueryService {
rpc GetUser (GetUserRequest) returns (GetUserResponse);
}
message CreateUserRequest {
string name = 1;
string email = 2;
}
message CreateUserResponse {
int32 result = 1;
}
message GetUserRequest {
int32 user_id = 1;
}
message GetUserResponse {
int32 id = 1;
string name = 2;
string email = 3;
}
```
**Note:** Svrnty.CQRS source generators automatically implement these services for you!
### Usage
```bash
# Using grpcurl
grpcurl -plaintext \
-d '{"name":"Alice","email":"alice@example.com"}' \
localhost:5000 \
CommandService/CreateUser
grpcurl -plaintext \
-d '{"userId":1}' \
localhost:5000 \
QueryService/GetUser
```
## Dual Protocol (Both HTTP & gRPC)
### What It Is
Run both HTTP and gRPC endpoints simultaneously, allowing clients to choose their preferred protocol.
### When to Use
**Best for:**
- Hybrid scenarios (public + internal APIs)
- Gradual migration from REST to gRPC
- Supporting multiple client types
- Maximum flexibility
### Example Setup
```csharp
var builder = WebApplication.CreateBuilder(args);
// Register CQRS
builder.Services.AddSvrntyCQRS();
builder.Services.AddDefaultCommandDiscovery();
builder.Services.AddDefaultQueryDiscovery();
// Register handlers
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
builder.Services.AddQuery<GetUserQuery, UserDto, GetUserQueryHandler>();
// Add HTTP support
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Add gRPC support
builder.Services.AddGrpc();
var app = builder.Build();
// Map HTTP endpoints
app.UseSvrntyCqrs();
// Map gRPC services
app.MapGrpcService<CommandServiceImpl>();
app.MapGrpcService<QueryServiceImpl>();
app.MapGrpcReflectionService();
// Enable Swagger
app.UseSwagger();
app.UseSwaggerUI();
app.Run();
```
### Benefits
-**Flexibility** - Clients choose protocol
-**Same codebase** - One implementation, two protocols
-**Gradual migration** - Transition clients over time
-**Best of both** - Public REST + internal gRPC
### Trade-offs
-**Slightly more complexity** - More configuration
-**Two sets of clients** - Maintain both if not auto-generated
-**Larger dependencies** - Both HTTP and gRPC packages
## Performance Comparison
### Latency
**gRPC:** ~50% lower latency than HTTP/JSON
```
gRPC: 1-2 ms
HTTP/JSON: 2-4 ms
```
*Results vary based on payload size and network conditions*
### Throughput
**gRPC:** ~2-3x higher throughput
```
gRPC: 50,000+ requests/sec
HTTP/JSON: 15,000-20,000 requests/sec
```
*On same hardware*
### Payload Size
**gRPC:** ~30-50% smaller payloads
```
Protocol Buffers: 100 bytes
JSON: 200-300 bytes
```
*For typical messages*
## Feature Comparison
| Feature | HTTP (Minimal API) | gRPC |
|---------|-------------------|------|
| **Performance** | Good | Excellent |
| **Browser support** | ✅ Yes | ❌ No (requires gRPC-Web) |
| **Caching** | ✅ Native HTTP caching | ❌ Not built-in |
| **Streaming** | ❌ No (without WebSockets) | ✅ Yes (bidirectional) |
| **Code generation** | ❌ No | ✅ Yes |
| **Human-readable** | ✅ JSON | ❌ Binary |
| **Tooling** | ✅ Excellent (Swagger, Postman) | ⚠️ Limited (grpcurl, Postman) |
| **Learning curve** | ✅ Low | ⚠️ Medium |
| **Type safety** | ⚠️ Runtime | ✅ Compile-time |
## Decision Matrix
### Choose HTTP If:
- ✅ You need browser/JavaScript clients
- ✅ Public API for third parties
- ✅ You want Swagger documentation
- ✅ Team is familiar with REST
- ✅ Caching is important
- ✅ Human readability matters
### Choose gRPC If:
- ✅ Microservices architecture
- ✅ Internal APIs only
- ✅ Performance is critical
- ✅ You need streaming
- ✅ Strong typing is important
- ✅ Polyglot environment (.NET, Go, Java, Python)
### Choose Both If:
- ✅ You have both public and internal clients
- ✅ You want flexibility
- ✅ You're migrating from REST to gRPC
- ✅ Different teams have different needs
## Migration Path
### Start with HTTP
1. Build with HTTP (easy to test, debug)
2. Add gRPC later if needed
3. Same handlers work for both
### Start with gRPC
1. Build with gRPC (for performance)
2. Add HTTP later for public API
3. Same handlers work for both
## Real-World Examples
### E-Commerce Platform
```csharp
// Public-facing API → HTTP
// Mobile app → HTTP
// Internal order processing → gRPC
// Payment service → gRPC
// Inventory service → gRPC
```
**Recommendation:** Dual protocol
### Internal Microservices
```csharp
// All service-to-service → gRPC
// Admin dashboard → HTTP (optional)
```
**Recommendation:** gRPC only
### SaaS Product
```csharp
// Customer API → HTTP
// JavaScript SDK → HTTP
// Webhooks → HTTP
```
**Recommendation:** HTTP only
## Next Steps
Congratulations! You've completed the Getting Started guide. You now know:
- ✅ What CQRS is and when to use it
- ✅ How to install Svrnty.CQRS
- ✅ How to create commands and queries
- ✅ How to add validation
- ✅ When to use HTTP vs gRPC
### Continue Learning
- **[Architecture](../architecture/README.md)** - Understand the framework design
- **[Core Features](../core-features/README.md)** - Deep dive into commands, queries, and dynamic queries
- **[HTTP Integration](../http-integration/README.md)** - Master HTTP endpoints
- **[gRPC Integration](../grpc-integration/README.md)** - Master gRPC services
- **[Event Streaming](../event-streaming/README.md)** - Build event-sourced applications
- **[Tutorials](../tutorials/README.md)** - Learn through comprehensive examples
### Try the Sample Project
Check out the complete sample application:
```bash
cd Svrnty.Sample
dotnet run
```
Visit:
- HTTP: `http://localhost:5000/swagger`
- gRPC: Use grpcurl or a gRPC client
## See Also
- [HTTP Integration Overview](../http-integration/README.md) - Complete HTTP guide
- [gRPC Integration Overview](../grpc-integration/README.md) - Complete gRPC guide
- [Endpoint Mapping](../http-integration/endpoint-mapping.md) - How HTTP endpoints work
- [Proto File Setup](../grpc-integration/proto-file-setup.md) - How .proto files work