🚀Transform your business with AI-powered process optimization
📋 Architecture Decision Records
⚙️ ADR-004: Centralized Configuration Management

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:

  1. Centralizes all configuration logic (loading, watching, validation)
  2. Provides component-specific APIs for typed configuration delivery
  3. Handles secrets management across all components
  4. Manages hot-reload capabilities with categorization
  5. Offers unified monitoring and operational visibility

Rationale

Why Centralization is the Right Choice

  1. Eliminate Duplication: Single implementation shared by all components
  2. Ensure Consistency: All components handle configuration the same way
  3. Reduce Complexity: Components focus on their core logic, not config management
  4. Improve Security: Centralized secret management and access control
  5. Enable Operations: Single point for configuration monitoring and management
  6. 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.yaml

Trade-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_membership

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

  1. Infrastructure First: Some decisions create foundational requirements that affect everything else
  2. User Questions Drive Architecture: The user's question led to a much better overall design
  3. Centralization vs. Distribution: Sometimes centralization is the right choice for operational simplicity
  4. 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.