ADR-004: Centralized Configuration Management
Status
✅ Accepted
Date
2024-01-15
Context
During the design of the Sindhan AI platform, we faced a critical infrastructure decision: how to handle configuration management across all components (Identity, Memory, Context, Awareness, Observability, Tools, Agent Interface, and Security & Privacy).
The Challenge
"each component will have configuration coming from a file.. what is your thought of having a separate configuration management that can take care of loading the file and monitor the change in the file content to upload it and etc."
The Problem
Without centralized configuration management, each component would need to:
- Implement its own file loading logic
- Handle file watching and change detection
- Manage configuration validation
- Deal with secret management independently
- Handle hot-reload capabilities separately
This would lead to:
- Code Duplication: Same logic repeated across 8+ components
- Inconsistency: Different components handling configs differently
- Maintenance Burden: Updates needed in multiple places
- Security Risks: Inconsistent secret handling
- Operational Complexity: No unified view of configuration state
Decision
Implement a centralized Configuration Management service that handles all configuration concerns for every component in the platform.
Architecture Decision
Create a dedicated Configuration Management Service as a foundational infrastructure component that:
- Centralizes all configuration logic (loading, watching, validation)
- Provides component-specific APIs for typed configuration delivery
- Handles secrets management across all components
- Manages hot-reload capabilities with categorization
- Offers unified monitoring and operational visibility
Rationale
Why Centralization is the Right Choice
- Eliminate Duplication: Single implementation shared by all components
- Ensure Consistency: All components handle configuration the same way
- Reduce Complexity: Components focus on their core logic, not config management
- Improve Security: Centralized secret management and access control
- Enable Operations: Single point for configuration monitoring and management
- Support Evolution: Easy to add new configuration sources and features
Alternatives Considered
Alternative 1: Component-Level Configuration
// Each component implements its own config management
impl IdentityComponent {
fn load_config() { /* file loading logic */ }
fn watch_config() { /* file watching logic */ }
fn validate_config() { /* validation logic */ }
}- ❌ Massive code duplication across 8+ components
- ❌ Inconsistent behavior and error handling
- ❌ Difficult to add new configuration sources
- ❌ Security vulnerabilities from inconsistent secret handling
Alternative 2: Shared Configuration Library
// Shared library used by all components
use sindhan_config_lib::ConfigLoader;
impl IdentityComponent {
fn new() -> Self {
let config = ConfigLoader::load("identity.toml")?;
// ...
}
}- ⚠️ Still requires each component to manage configuration lifecycle
- ⚠️ No centralized monitoring or operational visibility
- ⚠️ Difficult to coordinate updates across components
- ⚠️ Limited hot-reload capabilities
Alternative 3: Configuration as Environment Variables
# Environment-based configuration
IDENTITY_CACHE_SIZE=10000
MEMORY_MAX_SIZE=8192
CONTEXT_VECTOR_DIM=1536- ❌ No structured configuration or validation
- ❌ Difficult secret management
- ❌ No hot-reload capability
- ❌ Poor operational visibility
Consequences
Positive Outcomes
✅ Unified Configuration Experience: All components use the same patterns ✅ Reduced Component Complexity: Components focus on business logic ✅ Consistent Secret Management: Secure, audited secret handling ✅ Operational Excellence: Centralized monitoring and management ✅ Hot-Reload Capabilities: Sophisticated update mechanisms ✅ Type Safety: Strongly-typed configuration delivery ✅ Multiple Sources: Support for files, environment, remote configs ✅ Validation Framework: Schema-based validation for all components
Architecture Impact
New Infrastructure Component: Configuration Management Service
- Becomes a required dependency for all other components
- Must be highly available and performant
- Needs robust failure handling and fallback mechanisms
Component Integration Pattern:
// Standard pattern for all components
impl ComponentName {
async fn new(config_service: Arc<ConfigurationService>) -> Result<Self> {
let config = config_service.load_config::<ComponentConfig>().await?;
// Subscribe to updates
config_service.subscribe(|update| handle_update(update)).await?;
Ok(Self { config, config_service })
}
}Configuration Organization:
config/
├── components/
│ ├── identity.toml
│ ├── memory.toml
│ └── context.toml
├── environments/
│ ├── dev/
│ ├── staging/
│ └── production/
└── secrets/
└── secret-references.yamlTrade-offs and Challenges
⚠️ Additional Complexity: New service to develop, deploy, and maintain ⚠️ Single Point of Failure: Configuration service becomes critical infrastructure ⚠️ Bootstrap Dependency: Must solve cold-start problem for config service itself ⚠️ Network Dependency: Components depend on config service availability
Mitigation Strategies
High Availability:
- Multi-instance deployment with load balancing
- Local caching to survive temporary outages
- Graceful degradation using last-known-good configuration
Bootstrap Solution:
- Configuration service uses file-based config for its own startup
- Minimal initial configuration with ability to load full config after startup
Failure Handling:
- Components cache configuration locally
- Fallback to default configurations if service unavailable
- Automatic reconnection and synchronization
Implementation Details
Core Service Architecture
Component Registration
// Each component registers its configuration schema
impl IdentityComponent {
async fn register_with_config_service(&self) -> Result<()> {
let schema = ComponentSchema {
name: "identity",
version: "1.0.0",
fields: vec![
Field { name: "cache_size", type: "integer", required: true },
Field { name: "timeout_ms", type: "integer", required: true },
],
hot_reload_fields: vec!["cache_size", "timeout_ms"],
cold_reload_fields: vec!["database_url"],
};
self.config_service.register_component(schema).await
}
}Hot-Reload Implementation
Configuration Categories:
Hot-Reload: # Changes applied immediately
- cache_size
- timeout_values
- feature_flags
- log_levels
Cold-Reload: # Requires component restart
- database_connections
- network_bindings
- security_certificates
Immutable: # Cannot be changed
- component_id
- cluster_membershipFollow-up Actions
Completed
- ✅ Created comprehensive Configuration Management architecture
- ✅ Designed component-specific configuration handling
- ✅ Documented security and secrets management approach
- ✅ Established implementation patterns and best practices
- ✅ Created detailed integration documentation
Next Steps
- 📋 Implement Configuration Management service
- 📋 Create configuration schemas for all 8 core components
- 📋 Establish CI/CD integration for configuration validation
- 📋 Set up monitoring and alerting for configuration service
Component Integration
- 📋 Update all component architectures to use Configuration Management
- 📋 Create migration guides for existing configurations
- 📋 Establish testing patterns for configuration changes
Lessons Learned
- Infrastructure First: Some decisions create foundational requirements that affect everything else
- User Questions Drive Architecture: The user's question led to a much better overall design
- Centralization vs. Distribution: Sometimes centralization is the right choice for operational simplicity
- Type Safety Matters: Strongly-typed configuration prevents many runtime errors
Impact on Other Decisions
This decision influenced several subsequent architectural choices:
- Component isolation: Each component gets only its configuration
- Security patterns: Centralized secret management approach
- Operational patterns: Unified monitoring and management
- Development patterns: Standard component integration approach
Related Decisions
- ADR-005: Component-Specific Configuration Handling (builds on this foundation)
- ADR-001: Layered Documentation Architecture (same separation of concerns principle)
This decision established one of the most important infrastructure components in the Sindhan AI platform, providing a solid foundation for all configuration management needs while enabling operational excellence and security.