Most production software systems become unmanageable because configuration grows faster than the core codebase itself:
- documentation
- ownership
- validation
- mental models
The fix is not “less config.”
The fix is controlled configuration evolution.
The Real Root Cause
Configuration systems fail when they become:
| Problem | Example |
|---|---|
| Too expressive | Config behaves like a programming language |
| Too distributed | Rules spread across files/services |
| Too dynamic | Runtime behavior impossible to trace |
| Too layered | Overrides + inheritance + flags + templates |
| Unowned | Nobody governs the schema |
| Untestable | No simulation/debugging tools |
What You Should Do NOW (Before It Gets Bad)
1. Define Configuration Levels
Not all config should have equal power.
Create tiers:
Tier 1 → Simple constants
Tier 2 → Feature toggles
Tier 3 → Business rules
Tier 4 → Dynamic execution logic
Rule:
Only a few people can create Tier 4 configs.
Example
Good:
discount_percent: 10
Dangerous:
if:
customer.is_vip == true && region == "EU"
then:
invoke: dynamic_discount_engine
The second one is basically hidden software.
2. Limit Configuration Expressiveness
The biggest mistake:
Turning config into a programming language.
Avoid:
- embedded scripts
- arbitrary conditions
- recursive templates
- unlimited nesting
Bad:
rules:
- execute_python: |
if customer.balance > 500:
return "VIP"
Now your config system became an interpreter.
Good:
Use declarative constraints only:
segment: VIP
minimum_balance: 500
3. Create a “Configuration Budget”
Just like performance budgets.
Example:
- max nesting depth = 3
- max inheritance layers = 2
- max rule conditions = 5
- max config file size = 1000 lines
When limits exceeded:
- redesign architecture
- split domains
- simplify abstractions
4. Enforce Strong Schemas
Never allow “free-form” configuration.
Use:
- JSON Schema
- Pydantic
- Protocol Buffers
- OpenAPI
- typed YAML validation
Example in Python
from pydantic import BaseModel
class DiscountRule(BaseModel):
segment: str
discount_percent: int
min_purchase: float
Benefits:
- validation
- autocomplete
- discoverability
- safer refactoring
5. Make Configuration Observable
People panic when configs affect behavior invisibly.
You need:
A. Config tracing
Show:
text
WHY did customer receive 15% discount?
Answer:
text
Rule matched:
vip_discount.yaml → line 42
B. Config diff history
Track:
- who changed what
- when
- why
Use:
- Git
- audit logs
- change approval workflows
6. Separate Business Rules from System Configuration
One of the biggest architecture mistakes is mixing:
Infrastructure config
+
Business policy
+
Workflow logic
+
Feature flags
into one system.
Separate them.
Example
Infrastructure Config
database_pool_number: 20
Business Rule
vip_discounts: 15
Workflow Definition
when_signup:
- send_email
- create_trial
Different owners.
Different validation.
Different lifecycles.
7. Build Configuration Visualization Tools
If humans cannot SEE the system,
they cannot reason about it.
Create:
- dependency graphs
- rule trees
- override chains
- execution flow diagrams
8. Introduce Configuration Governance
At scale, configs need architecture review.
Create:
- config review process
- schema evolution process
- deprecation policy
- ownership registry
Example
Every config must have:
owner: pricing-team
created_at: 2026-01-10
expires_at: 2027-01-10
Yes — configs should expire.
Dead config is one of the biggest complexity multipliers.
9. Prefer “Opinionated Systems” Over Infinite Flexibility
The safest platforms intentionally restrict users.
Good systems say:
“You can only do these 5 supported things.”
Bad systems say:
“You can do anything.”
“Anything” eventually becomes:
- impossible debugging
- impossible onboarding
- impossible predictability
10. Periodically Delete Features
Configuration complexity grows like entropy.
You should have:
- cleanup sessions
- simplification sprints
- regular review periods
Ask:
- Which feature flags are no longer used?
- Which rules are outdated?
- Which parts can be combined?
- Which ideas made the system more confusing instead of helping?
The Most Important Principle
Configuration Should Describe Reality — Not Replace Code
Good config:
tax_rate: 0.20
Bad config:
if:
region == "EU" &&
order.total > 100 &&
user.is_vip == true &&
inventory.dynamic() &&
seasonality.predict()
then:
execute: custom_tax_plugin
At that point:
you secretly rebuilt a programming language badly.
A Practical Strategy for Your Current Project
If you are building something today:
Phase 1 — Keep It Hardcoded
Early startup stage:
- optimize for clarity
- not flexibility
Phase 2 — Extract Stable Variability
Only configurable things that:
- change frequently
- differ by customer
- differ by environment
Phase 3 — Introduce Typed Rules
Use:
- schemas
- validation
- bounded rule systems
Phase 4 — Add Governance BEFORE Scale
Do not wait until chaos.
Add:
- ownership
- reviews
- tooling
- tracing
- visualization early.
The Golden Rule
A good configuration system should answer:
- What changed?
- Why did this happen?
- Who owns this?
- What depends on this?
- Can I safely modify it?
- Can a new engineer understand it in 2 hours?
If the answer becomes “no” then your configuration system is already facing toward collapse.
BTW, feel free to follow me on Linkedin!
Top comments (0)