From c737c79191f006833239dec7c7605e80e94f3fd1 Mon Sep 17 00:00:00 2001 From: Gabriel Radureau Date: Sat, 4 Apr 2026 21:57:40 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20docs:=20add=20gRPC=20adoption=20?= =?UTF-8?q?strategy=20ADR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- adr/0014-grpc-adoption-strategy.md | 281 +++++++++++++++++++++++++++++ adr/README.md | 2 + 2 files changed, 283 insertions(+) create mode 100644 adr/0014-grpc-adoption-strategy.md diff --git a/adr/0014-grpc-adoption-strategy.md b/adr/0014-grpc-adoption-strategy.md new file mode 100644 index 0000000..36fc35c --- /dev/null +++ b/adr/0014-grpc-adoption-strategy.md @@ -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"} +``` \ No newline at end of file diff --git a/adr/README.md b/adr/README.md index 99d8397..c4d60fb 100644 --- a/adr/README.md +++ b/adr/README.md @@ -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