Configuration Layers
Manager uses a three-layer configuration system that provides flexible settings inheritance from project defaults down to what one tenant sees in one application.
The Three Layers
┌─────────────────────────────────────┐
│ Project Settings │ ← Most General
│ (Defaults for all tenants/apps) │
└─────────────────────────────────────┘
↓ inherits
┌─────────────────────────────────────┐
│ Tenant Settings │ ← Middle Layer
│ (Defaults for this customer org) │
└─────────────────────────────────────┘
↓ inherits
┌─────────────────────────────────────┐
│ Tenant × Application Settings │ ← Most Specific (leaf)
│ (Tenant2Application: one customer │
│ org's use of one application) │
└─────────────────────────────────────┘The leaf layer is the Tenant2Application row
Since the Wave 3 re-architecture the cascade leaf is the Tenant2Application join — the per-(tenant, application) settings for one customer organization's use of one application. The Manager merges project → tenant → tenant2application, and returns 404 if the application is not enabled for the tenant. Config is fetched per (application, tenant): GET /api/frontend-config/:application_id/:tenant_id. See Multi-tenancy and the Migration Guide.
How Inheritance Works
When an application needs a setting for a tenant:
- Check Tenant × Application - Look in the
Tenant2Applicationsettings first - Check Tenant - If not found, look in tenant settings
- Check Project - If still not found, look in project settings
- Use Default - If nowhere, use system default
Inheritance Example
The values below are illustrative custom key-value pairs (stored in the settings' KeyValuePairs):
Project: Customer Portal
{
"theme": "light",
"locale": "en",
"features": ["basic-dashboard"]
}Tenant: ACME Corp
{
"theme": "dark",
"support_email": "support@acme.com"
}Tenant × Application: ACME Corp × Mobile App (the Tenant2Application leaf)
{
"locale": "es",
"features": ["chat"]
}Effective Configuration for Mobile App as ACME Corp sees it:
{
"theme": "dark", // from Tenant (overrides Project)
"locale": "es", // from Tenant × Application (overrides Project)
"support_email": "support@acme.com", // from Tenant
"features": ["chat"] // from Tenant × Application (overrides Project)
}Configuration Types
Backend Settings
Server-side configuration:
- Modules - Which backend features are enabled
- Key-Value Pairs - Custom parameters
Example:
{
"EnabledModules": ["auth", "api", "analytics"],
"KeyValuePairs": [
{ "Key": "api_version", "Value": "v2" },
{ "Key": "rate_limit", "Value": "1000" }
]
}Frontend Settings
Client-side configuration:
- Modules - UI components with versions
- Themes - Available and default theme
- Locales - Languages and default
- Key-Value Pairs - Custom UI parameters
Example:
{
"EnabledModules": ["dashboard@1.2.0"],
"EnabledThemes": ["light", "dark"],
"DefaultTheme": "light",
"EnabledLocales": ["en", "es"],
"DefaultLocale": "en"
}When to Configure at Each Layer
Project Level
Use for:
- Product line specific features
- Common settings for related tenants/apps
- Shared modules across all tenants
- Environment-specific defaults (dev/qas/run environments)
Examples:
{
"features": ["advanced-reporting", "api-access"],
"EnabledModules": ["analytics", "webhooks"],
"environment": "production"
}Tenant Level
Use for:
- Organization-wide branding (logo, colors)
- Company-wide settings (support email, timezone)
- Default language for tenant's apps
- Security policies per customer
Examples:
{
"theme": "corporate-blue",
"locale": "en",
"support_email": "support@company.com",
"logo_url": "https://cdn.company.com/logo.png"
}Application Level
Use for:
- App-specific customizations
- Overrides for special cases
- Unique features per app
- A/B testing variants
Examples:
{
"locale": "fr", // This app uses French
"theme": "custom-dark" // Custom theme
}Viewing Effective Configuration
In Settings Editor
- Navigate to Application → Settings
- Look for Layer Viewer sidebar
- See configuration from all layers:
- Values in bold = defined at current layer
- Values in gray = inherited from parent
- Highlighted = overriding parent value
Example Layer Viewer
┌─ Project (Customer Portal) ───────┐
│ theme: "light" │
│ locale: "en" │
└───────────────────────────────────┘
↓
┌─ Tenant (ACME Corp) ──────────────┐
│ theme: "dark" ← OVERRIDES │
│ locale: "en" ← inherited │
│ support_email: "support@acme.com" │
└───────────────────────────────────┘
↓
┌─ ACME Corp × Mobile App ──────────┐
│ theme: "dark" ← inherited │
│ locale: "es" ← OVERRIDES │
│ support_email: "..." ← inherited │
└───────────────────────────────────┘Override Strategies
The merge behavior depends on the field:
Replaced Fields
EnabledModules, EnabledThemes, and EnabledLocales are completely replaced when a lower layer defines a non-empty value:
Project: EnabledModules: ["reporting", "analytics"]Application: EnabledModules: ["admin-panel"]Result: Only ["admin-panel"] (completely replaced)
DefaultTheme and DefaultLocale are overridden whenever a lower layer sets a non-empty value.
Merged Fields
AvailableModules, AvailableThemes, and AvailableLocales are merged across layers (union with duplicates removed). KeyValuePairs are merged by key, with the more specific layer winning on conflicting keys.
Conditional Overrides
Override only in specific cases:
Example: Different theme for mobile app:
- Project/Tenant:
theme: "standard" - Mobile App:
theme: "mobile-optimized" - Web App: (inherits
"standard")
Best Practices
DRY (Don't Repeat Yourself)
[NO] Bad: Define same setting at every level
Project: support_email = "support@company.com"
Tenant: support_email = "support@company.com"
App 1: support_email = "support@company.com"
App 2: support_email = "support@company.com"[OK] Good: Define once at project level
Project: support_email = "support@company.com"
(Tenant and Apps inherit)Override Only When Necessary
Only set values at lower layers if they differ from parent:
Project: theme = "light"
Tenant: (no theme setting - inherits "light")
Special App: theme = "dark" ← Only this app needs overrideDocument Overrides
When overriding, document why:
{
"theme": "high-contrast",
"_comment": "Accessibility app requires high contrast theme"
}Test Configuration Changes
- Make changes in development/staging first
- View effective configuration
- Test application behavior
- Apply to production
Common Patterns
Multi-Environment Setup
Environments are a first-class entity (dev, qas, run) — not tenants. The same application row is deployed per environment; environment-specific settings live on the project (or are copied between environments), and per-customer overrides live on the tenant2application leaf:
Project: Customer Portal
├─ Environments:
│ ├─ dev (debug on, mock data)
│ ├─ qas (debug on)
│ └─ run (debug off)
├─ Applications: Portal (one row, deployed per environment)
└─ Tenants: Customer A, Customer B (each enables Portal)Never model an environment as a tenant. See Multi-tenancy.
Multi-Brand / Multi-Customer Setup
Use tenants for customer organizations (or brands) within a project, and put per-customer overrides on the enablement leaf:
Project: Multi-Brand Platform
├─ Tenant: Brand A
│ └─ Brand A × App: { theme: "brand-a-blue", logo: "brand-a.png" }
└─ Tenant: Brand B
└─ Brand B × App: { theme: "brand-b-green", logo: "brand-b.png" }Feature Flags
Control features at project level:
Project: Enterprise
└─ settings: { features: ["advanced-analytics", "api-access", "sso"] }
Project: Basic
└─ settings: { features: ["basic-analytics"] }Troubleshooting
Setting Not Taking Effect
Check:
- Is it defined at a more specific layer?
- Is the setting key spelled correctly?
- View effective configuration to see what value is being used
- Is application caching the configuration?
Unexpected Value
Debug:
- Open Layer Viewer
- Check each layer from top to bottom
- Find where the value is defined
- Verify that's the intended behavior
Cannot Override Setting
Reason: Application may not support overriding that setting
Solution: Check application documentation for configurable settings
See Also
- Settings Editor - Edit configurations
- Multi-tenancy - Understanding tenants
- Managing Projects - Project organization
- Managing Applications - App configuration