Evolutionary Architecture
Designing for guided incremental change rather than for a correct end state, because the requirements that will matter most are not yet known.
Evolutionary architecture accepts that the design will be wrong and optimises for the cost of being wrong. Its central question is not "is this the right structure?" but "how expensive is it to change this structure when we learn something?"
The three ingredients
- Guided change. Automated fitness functions that assert an architectural property still holds — no cyclic dependencies, p99 within budget, no module reaching across a boundary.
- Incremental change. The ability to release a small change safely: trunk-based development, feature flags, expand-and-contract schema migrations, canaries.
- Appropriate coupling. Boundaries placed where change is expected, so evolution is local.
Industry example
Meta's approach to schema and API evolution at very large scale is instructive because it inverts the usual assumption. With billions of users and mobile clients that cannot be upgraded in lockstep, there is no such thing as a coordinated change; every change must be compatible with every previously deployed client.
That forces a specific discipline: additive changes only, fields deprecated but never removed on a whim, and long overlap windows where old and new behaviour coexist behind flags while data migrates in the background. Product experiments run continuously behind those flags, which means the architecture must tolerate many simultaneous variants of behaviour as a normal state rather than as an exception.
The architectural consequence is that backward compatibility becomes a structural property, not a release-note courtesy. Systems that cannot express two versions of a behaviour simultaneously cannot evolve at that scale.
Failure scenarios
- Big-bang redesign. An eighteen-month rewrite against requirements that changed in month four.
- Evolution without fitness functions. The architecture drifts; nobody notices until it is a rewrite again.
- Reversible decisions treated as irreversible. Endless debate over something that could have been tried in a week and undone in a day.
Trade-off
Evolvability costs present efficiency: dual-writing during a migration, maintaining two code paths, carrying deprecated fields. Pay it where change is likely and refuse it where it is not — some decisions genuinely are one-way and deserve the deliberation.
Interview question
"How would you migrate a hot table's schema with zero downtime and the ability to roll back at any point?"