- Document hybrid REST/gRPC approach (ADR-0014) - Define phased implementation strategy - Establish future triggers for gRPC adoption - Update ADR README with new entry - Maintain REST as primary protocol for now Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
281 lines
7.5 KiB
Markdown
281 lines
7.5 KiB
Markdown
# 14. gRPC Adoption Strategy
|
|
|
|
**Date:** 2026-04-05
|
|
**Status:** Accepted
|
|
**Authors:** DanceLessonsCoach Team
|
|
|
|
## Context
|
|
|
|
The DanceLessonsCoach project currently uses REST/JSON for all API communication. As the project evolves, we need to determine when and how to adopt gRPC for performance-critical and internal communication scenarios.
|
|
|
|
## Decision Drivers
|
|
|
|
* **Current Needs**: Simple API with good REST support
|
|
* **Future Growth**: Potential for mobile apps and microservices
|
|
* **Performance**: Current REST performance is adequate
|
|
* **Complexity**: gRPC adds significant architectural complexity
|
|
* **Team Expertise**: Strong REST/JSON experience, limited gRPC experience
|
|
* **Ecosystem**: Existing tooling and documentation for REST
|
|
|
|
## Considered Options
|
|
|
|
### Option 1: Immediate Full gRPC Adoption
|
|
**Description:** Replace all REST endpoints with gRPC immediately
|
|
|
|
**Pros:**
|
|
- Future-proof architecture
|
|
- Best performance from day one
|
|
- Clean slate design
|
|
|
|
**Cons:**
|
|
- Significant development effort
|
|
- Steep learning curve
|
|
- Breaking changes for existing clients
|
|
- Overkill for current needs
|
|
|
|
### Option 2: Hybrid Approach (Recommended)
|
|
**Description:** Keep REST for public API, add gRPC for internal/services
|
|
|
|
**Pros:**
|
|
- Backward compatibility maintained
|
|
- Gradual learning curve
|
|
- Performance where needed
|
|
- Flexibility for future growth
|
|
|
|
**Cons:**
|
|
- More complex architecture
|
|
- Need to maintain both protocols
|
|
- Gateway translation overhead
|
|
|
|
### Option 3: REST Only
|
|
**Description:** Continue with REST/JSON only
|
|
|
|
**Pros:**
|
|
- Simple and well-understood
|
|
- Good tooling and debugging
|
|
- No architectural changes needed
|
|
|
|
**Cons:**
|
|
- May limit future scalability
|
|
- Performance ceiling
|
|
- Harder to add real-time features
|
|
|
|
### Option 4: gRPC for New Features Only
|
|
**Description:** Use REST for existing, gRPC for new features
|
|
|
|
**Pros:**
|
|
- No breaking changes
|
|
- Learn gRPC gradually
|
|
- Performance for new features
|
|
|
|
**Cons:**
|
|
- Inconsistent API surface
|
|
- Complex migration path
|
|
- Harder to maintain coherence
|
|
|
|
## Decision Outcome
|
|
|
|
**Chosen option:** **Option 2 - Hybrid Approach**
|
|
|
|
### Implementation Strategy
|
|
|
|
**Phase 1: Preparation (Current)**
|
|
- ✅ Document gRPC adoption strategy (this ADR)
|
|
- ✅ Implement OpenAPI/Swagger for REST (ADR-0013)
|
|
- ✅ Continue REST development
|
|
- ✅ Monitor performance metrics
|
|
|
|
**Phase 2: Foundation (When Needed)**
|
|
```bash
|
|
# Add gRPC dependencies
|
|
go get google.golang.org/grpc
|
|
go get google.golang.org/protobuf
|
|
|
|
# Create proto directory
|
|
mkdir -p proto/greet
|
|
|
|
# Add basic protobuf definition
|
|
cat > proto/greet/greet.proto << 'EOF'
|
|
syntax = "proto3";
|
|
|
|
package greet.v1;
|
|
|
|
service GreetService {
|
|
rpc Greet (GreetRequest) returns (GreetResponse);
|
|
}
|
|
|
|
message GreetRequest {
|
|
string name = 1;
|
|
}
|
|
|
|
message GreetResponse {
|
|
string message = 1;
|
|
}
|
|
EOF
|
|
```
|
|
|
|
**Phase 3: Internal Services (Future)**
|
|
```go
|
|
// When adding internal services:
|
|
// User Service <--gRPC--> Greet Service
|
|
// Analytics Service <--gRPC--> Greet Service
|
|
|
|
func (s *Server) startGRPC() {
|
|
if s.config.GRPC.Enabled {
|
|
lis, err := net.Listen("tcp", s.config.GRPC.Address)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("Failed to listen for gRPC")
|
|
return
|
|
}
|
|
|
|
grpcServer := grpc.NewServer()
|
|
proto.RegisterGreetServiceServer(grpcServer, s.grpcHandler)
|
|
|
|
log.Info().Str("address", s.config.GRPC.Address).Msg("Starting gRPC server")
|
|
if err := grpcServer.Serve(lis); err != nil {
|
|
log.Error().Err(err).Msg("gRPC server failed")
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Phase 4: Mobile Clients (Future)**
|
|
```bash
|
|
# When adding mobile apps:
|
|
# iOS/Android App --gRPC--> DanceLessonsCoach
|
|
|
|
# Generate mobile clients
|
|
protoc --plugin=protoc-gen-grpc=`which grpc_swift_plugin` \
|
|
--grpc_swift_out=. \
|
|
proto/greet/greet.proto
|
|
```
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
|
|
1. **Backward Compatibility**: Existing REST clients continue working
|
|
2. **Performance**: gRPC available when needed for critical paths
|
|
3. **Flexibility**: Can choose right protocol for each use case
|
|
4. **Gradual Learning**: Team can learn gRPC at appropriate pace
|
|
5. **Future-Proof**: Architecture ready for growth
|
|
|
|
### Negative
|
|
|
|
1. **Complexity**: More moving parts to maintain
|
|
2. **Overhead**: Gateway translation between protocols
|
|
3. **Learning Curve**: Team needs to learn gRPC eventually
|
|
4. **Build Complexity**: Additional build steps for protobuf
|
|
|
|
### Mitigations
|
|
|
|
1. **Documentation**: Comprehensive gRPC guides and examples
|
|
2. **Training**: Gradual team education on gRPC concepts
|
|
3. **Tooling**: Automate protobuf generation in CI/CD
|
|
4. **Monitoring**: Track protocol usage and performance
|
|
|
|
## Verification
|
|
|
|
### Success Criteria
|
|
|
|
1. ✅ REST API remains fully functional
|
|
2. ✅ gRPC can be enabled via configuration
|
|
3. ✅ No performance regression in REST paths
|
|
4. ✅ Clear documentation for both protocols
|
|
5. ✅ CI/CD supports both REST and gRPC testing
|
|
|
|
### Test Plan
|
|
|
|
```bash
|
|
# Test REST still works
|
|
curl http://localhost:8080/api/v1/greet/John
|
|
# Expected: {"message":"Hello John!"}
|
|
|
|
# Test gRPC can be disabled by default
|
|
export DLC_GRPC_ENABLED=false
|
|
./bin/server
|
|
# Expected: Only REST server starts
|
|
|
|
# Test configuration validation
|
|
DLC_GRPC_ENABLED=true DLC_GRPC_PORT=invalid ./bin/server
|
|
# Expected: Configuration error, clean exit
|
|
```
|
|
|
|
## Related Decisions
|
|
|
|
- [ADR-0002: Chi Router](adr/0002-chi-router.md) - Current routing framework
|
|
- [ADR-0013: OpenAPI/Swagger](adr/0013-openapi-swagger-toolchain.md) - REST documentation
|
|
- [ADR-0010: API v2 Feature Flag](adr/0010-api-v2-feature-flag.md) - Versioning strategy
|
|
|
|
## Future Triggers
|
|
|
|
**Consider implementing gRPC when any of these occur:**
|
|
|
|
1. **Mobile App Development**: Need for efficient mobile communication
|
|
2. **Microservices**: Adding internal services that need gRPC
|
|
3. **Performance Issues**: REST becomes bottleneck at scale
|
|
4. **Real-time Features**: Need for streaming/bidirectional communication
|
|
5. **Team Readiness**: Team comfortable with gRPC concepts
|
|
|
|
## Revision History
|
|
|
|
- **1.0 (2026-04-05)**: Initial decision
|
|
- **1.1 (2026-04-05)**: Added implementation phases and triggers
|
|
|
|
## References
|
|
|
|
- [gRPC Documentation](https://grpc.io/docs/)
|
|
- [Protocol Buffers](https://developers.google.com/protocol-buffers)
|
|
- [gRPC vs REST Comparison](https://grpc.io/blog/grpc-vs-rest)
|
|
- [Hybrid API Design](https://cloud.google.com/blog/products/api-management/designing-hybrid-apis)
|
|
|
|
**Approved by:** DanceLessonsCoach Team
|
|
**Effective Date:** 2026-04-05
|
|
|
|
## Configuration Reference
|
|
|
|
```yaml
|
|
# config.yaml example for future gRPC support
|
|
grpc:
|
|
enabled: false # Set to true to enable gRPC server
|
|
host: "0.0.0.0"
|
|
port: "50051"
|
|
reflection: true # Enable for development
|
|
max_msg_size: 4194304 # 4MB max message size
|
|
|
|
rest:
|
|
enabled: true # REST remains enabled
|
|
host: "0.0.0.0"
|
|
port: "8080"
|
|
```
|
|
|
|
## Migration Checklist
|
|
|
|
- [ ] Add gRPC dependencies to go.mod
|
|
- [ ] Create proto directory structure
|
|
- [ ] Add basic greet.proto definition
|
|
- [ ] Implement gRPC server (disabled by default)
|
|
- [ ] Add configuration options
|
|
- [ ] Update CI/CD for protobuf generation
|
|
- [ ] Add gRPC health checks
|
|
- [ ] Document gRPC usage
|
|
- [ ] Performance benchmarking
|
|
- [ ] Gradual rollout to production
|
|
|
|
## Monitoring Metrics
|
|
|
|
**Recommended metrics to track:**
|
|
|
|
```prometheus
|
|
# REST metrics
|
|
rest_requests_total{endpoint="/api/v1/greet", status="200"}
|
|
rest_response_time_seconds{quantile="0.95"}
|
|
|
|
# gRPC metrics (when enabled)
|
|
grpc_server_handling_seconds{grpc_method="Greet", grpc_code="OK"}
|
|
grpc_server_started_total{grpc_method="Greet"}
|
|
|
|
# Comparison metrics
|
|
api_latency_comparison{protocol="rest", endpoint="/greet"}
|
|
api_latency_comparison{protocol="grpc", endpoint="/greet"}
|
|
``` |