📝 docs: add gRPC adoption strategy ADR
- 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>
This commit is contained in:
281
adr/0014-grpc-adoption-strategy.md
Normal file
281
adr/0014-grpc-adoption-strategy.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# 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"}
|
||||
```
|
||||
@@ -71,6 +71,8 @@ Chosen option: "[Option 1]" because [justification]
|
||||
* [0010-api-v2-feature-flag.md](0010-api-v2-feature-flag.md) - API v2 implementation with feature flag control
|
||||
* [0011-validation-library-selection.md](0011-validation-library-selection.md) - Selection of go-playground/validator for input validation
|
||||
* [0012-git-hooks-staged-only-formatting.md](0012-git-hooks-staged-only-formatting.md) - Git hooks format only staged Go files
|
||||
* [0013-openapi-swagger-toolchain.md](0013-openapi-swagger-toolchain.md) - OpenAPI/Swagger toolchain selection
|
||||
* [0014-grpc-adoption-strategy.md](0014-grpc-adoption-strategy.md) - Hybrid REST/gRPC adoption strategy
|
||||
|
||||
## How to Add a New ADR
|
||||
|
||||
|
||||
Reference in New Issue
Block a user