📝 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:
2026-04-04 21:57:40 +02:00
parent f0e313108c
commit c737c79191
2 changed files with 283 additions and 0 deletions

View 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"}
```

View File

@@ -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