Updated existing Architecture Decision Records: - Added user authentication references to ADR-0008 (BDD Testing) - Updated ADR-0016 (CI/CD Pipeline) with authentication workflow - Enhanced ADR-0017 (Trunk-based Development) with BDD integration - Added security considerations to multiple ADRs - Updated cross-references throughout documentation Removed deprecated files: - docker-compose.cicd-test.yml (replaced by docker-compose.yml) Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
5.8 KiB
5.8 KiB
10. API v2 Feature Flag Implementation
Date: 2026-04-04 Status: Accepted Authors: AI Agent
Context
The dance-lessons-coach application needed to add a new API version (v2) that provides different greeting behavior while maintaining backward compatibility with the existing v1 API. The v2 API should only be available when explicitly enabled via a feature flag.
Decision
Implement API v2 with the following characteristics:
- Separate Service Implementation: Create a new
ServiceV2that implements different greeting logic - Feature Flag Control: Add a configuration flag
api.v2_enabledto control v2 availability - Environment Variable Support: Allow enabling via
DLC_API_V2_ENABLEDenvironment variable - Default Disabled: v2 API is disabled by default to maintain backward compatibility
- Separate Routing: v2 endpoints use
/api/v2prefix, separate from/api/v1
Implementation Details
Service Layer
- New Service:
pkg/greet/greet_v2.gowithServiceV2struct - New Interface:
GreeterV2interface withGreetV2()method - Different Behavior: Returns "Hello my friend !" instead of "Hello !"
- Empty Name Handling: Returns "Hello my friend!" when name is empty
API Layer
- New Handler:
pkg/greet/api_v2.gowithapiV2GreetHandlerstruct - New Interface:
ApiV2Greetinterface withRegisterRoutes()method - POST Endpoint:
/api/v2/greetexpects JSON body withnamefield - JSON Response: Returns
{"message": "<greeting>"}format
Configuration
- New Config Struct:
APIConfiginpkg/config/config.go - Feature Flag:
V2Enabled boolfield - Environment Variable:
DLC_API_V2_ENABLEDbinding - Default Value:
false(disabled by default) - Config Method:
GetV2Enabled()method onConfigstruct
Server Integration
- Conditional Routing: v2 routes only registered when
config.GetV2Enabled()returns true - Separate Registration:
registerApiV2Routes()method in server - Same Middleware: v2 routes use same middleware stack as v1
- Graceful Coexistence: Both v1 and v2 can run simultaneously
Testing
- Unit Tests:
pkg/greet/greet_v2_test.gowith table-driven tests - BDD Tests: Extended
features/greet.featurewith v2 scenarios - Step Definitions: Added v2-specific steps in
pkg/bdd/steps/steps.go - Test Server: Modified test server to enable v2 by default for testing
Consequences
Positive
- Backward Compatibility: v1 API continues to work unchanged
- Feature Flag Control: v2 can be enabled/disabled without code changes
- Clean Separation: v1 and v2 implementations are independent
- Test Coverage: Comprehensive BDD tests validate both versions
- Configuration Flexibility: Can be controlled via config file or environment variables
Negative
- Increased Complexity: More code paths to maintain
- Configuration Management: Additional configuration option to document
- Testing Overhead: Need to test both enabled and disabled states
- Deployment Considerations: Need to ensure feature flag is set correctly in production
Alternatives Considered
1. Always Enable v2
- Rejected: Would break backward compatibility
- Reason: Customers might not be ready for API changes
2. Replace v1 with v2
- Rejected: Would be a breaking change
- Reason: Violates semantic versioning principles
3. Use URL Query Parameter
- Rejected: Less clean API design
- Reason: Version should be in URL path, not query string
4. Use Header-Based Versioning
- Rejected: More complex for clients
- Reason: URL-based versioning is more RESTful and discoverable
Validation
Test Results
# Unit tests pass
go test ./pkg/greet/...
# BDD tests pass
go test ./features/... -v
# All scenarios pass:
- Default greeting (v1)
- Personalized greeting (v1)
- v2 greeting with JSON POST request
- v2 default greeting with empty name
- Health check returns healthy status
Manual Testing
# Test v2 disabled (default)
curl -X POST http://localhost:8080/api/v2/greet -H "Content-Type: application/json" -d '{"name":"John"}'
# Expected: 404 Not Found
# Test v2 enabled
DLC_API_V2_ENABLED=true go run ./cmd/server
curl -X POST http://localhost:8080/api/v2/greet -H "Content-Type: application/json" -d '{"name":"John"}'
# Expected: {"message":"Hello my friend John!"}
# Test v1 still works
curl http://localhost:8080/api/v1/greet/John
# Expected: {"message":"Hello John!"}
Migration Path
- Deploy with v2 Disabled: Initial deployment keeps v2 disabled
- Enable in Staging: Test v2 in staging environment
- Gradual Rollout: Enable v2 for select customers
- Monitor: Track usage and performance
- Full Enable: Enable v2 for all customers when ready
- Deprecation: Eventually deprecate v1 (future decision)
Future Considerations
- Deprecation Timeline: When to deprecate v1
- Version Negotiation: Content negotiation for API versions
- OpenAPI Documentation: Update Swagger/OpenAPI docs for v2
- Client SDKs: Update client libraries to support v2
- Metrics: Add metrics to track v1 vs v2 usage
References
Changelog Entry
### 2026-04-04 - API v2 Implementation
- ✅ Added /api/v2/greet POST endpoint with JSON request/response
- ✅ Implemented ServiceV2 with "Hello my friend <name>!" greeting format
- ✅ Added api.v2_enabled feature flag (default: false)
- ✅ Extended BDD tests to cover v2 scenarios
- ✅ Maintained full backward compatibility with v1 API
- ✅ Added DLC_API_V2_ENABLED environment variable support