Config Service Architecture
The Config Service provides centralized, versioned configuration management for all 24 platform services. It implements a hierarchical configuration model with four override levels, feature flags for gradual rollouts, and Redis Pub/Sub-based change distribution for zero-downtime updates.
2.3.D.1Configuration Hierarchy
Configuration values are resolved through a four-level hierarchy, where higher-specificity levels override lower ones:
Level 1: Global Defaults
| (platform-wide defaults for all services)
|
+--> Level 2: Environment Overrides (dev, staging, prod)
| (environment-specific settings)
|
+--> Level 3: Service-Specific Overrides
| (settings for a specific service)
|
+--> Level 4: Tenant-Specific Overrides
(custom settings for a specific tenant)Resolution example:
Key: "ai.model.default"
Level 1 (Global): "gpt-3.5-turbo"
Level 2 (Production): "gpt-4o"
Level 3 (ai-service): not set (inherits "gpt-4o")
Level 4 (acme-corp): "gpt-4-turbo" <-- Resolved value for acme-corp
Level 4 (globex): not set <-- Resolves to "gpt-4o" (level 2)2.3.D.2Feature Flags
Feature flags are a special category of configuration that supports gradual rollouts:
public class FeatureFlag {
String key; // e.g., "ai.streaming.enabled"
boolean globalDefault; // Platform-wide default
Map<String, Boolean> tenantOverrides; // Per-tenant overrides
Set<String> enabledTiers; // Tiers where feature is enabled
int rolloutPercentage; // Gradual rollout (0-100)
}Evaluation logic:
1. Check tenant-specific override --> if set, return it
2. Check tier enablement --> if tenant's tier is in enabledTiers, return true
3. Check rollout percentage --> hash(tenantId + flagKey) % 100 < rolloutPercentage
4. Return globalDefaultThis allows progressive feature rollouts: first enable for Enterprise tenants, then Professional, then roll out to a percentage of Free tier tenants.
Key APIs:
| Endpoint | Method | Description |
|---|---|---|
/api/v1/config/:service/:profile | GET | Retrieve resolved configuration |
/api/v1/config/:service | PUT | Update service configuration |
/api/v1/config/tenants/:tenantId | GET/PUT | Tenant-specific configuration |
/api/v1/config/features | GET/POST | Feature flag management |
/api/v1/config/features/:key/evaluate | GET | Evaluate flag for tenant |
/api/v1/config/history | GET | Configuration version history |
/api/v1/config/rollback/:version | POST | Rollback to previous version |
2.3.D.3Change Distribution
When a configuration value is updated, the config-service distributes the change to all running services:
1. Admin updates config via PUT /api/v1/config/{service}
2. Config-service validates the new value against schema
3. Config-service persists the new value with a version number
4. Config-service publishes to Redis Pub/Sub channel "config:changes":
{
"key": "ai.model.default",
"service": "ai-service",
"tenantId": null, // null = global change
"version": 42,
"changedBy": "admin-user-123"
}
5. All subscribed services receive the notification
6. Each service calls GET /api/v1/config/{service}/{profile} to reload
7. Local configuration cache is updated without restartLatency: Configuration changes propagate to all services within 100-500ms of the update, depending on Redis Pub/Sub delivery and the service's poll interval.
2.3.D.4Version History and Rollback
Every configuration change is versioned in PostgreSQL:
| Column | Type | Description |
|---|---|---|
version | BIGINT | Auto-incrementing version number |
key | VARCHAR | Configuration key |
value | JSONB | Configuration value |
previous_value | JSONB | Value before this change |
changed_by | VARCHAR | User who made the change |
changed_at | TIMESTAMP | Timestamp of the change |
reason | VARCHAR | Optional change reason |
Rollback restores a previous version and publishes a new change event, ensuring all services pick up the reverted value.
2.3.D.5Bootstrap Configuration
The config-service itself cannot depend on the config-service for its own configuration. It uses file-based bootstrap configuration loaded from Helm values:
# values.yaml for config-service
config:
bootstrap:
database:
host: "postgresql"
port: 5432
name: "config"
redis:
host: "redis"
port: 6379
server:
port: 8888This avoids the circular dependency that would occur if the config-service tried to fetch its own configuration from itself.
Related Sections
- Control Plane Overview -- All Control Plane services
- Redis Pub/Sub -- Real-time notification patterns
- Multi-Tenancy -- Tenant-specific configuration