Modern systems evolve through more than code deploys.
External state changes continuously — schemas, identity mappings, policies, configuration, integrations.
This series examines how to govern that evolution deliberately.
It does not focus on deployment pipelines, it focuses on system behavior over time.
The Progression
This page outlines the conceptual build of the series:
1. The Blind Spot
The biggest blind spot in modern microservices: evolving external systems
Why evolving external systems is the hidden risk in distributed architectures — and why code deploy discipline alone does not solve it.
2. The CI/CD Gap
CI/CD deploys code. It doesn't evolve external systems.
Delivery pipelines govern artifact propagation. They do not govern cross-boundary state sequencing. This distinction sets up the structural gap.
3. The Discipline
Change-as-Code: The discipline modern systems have been missing
Introducing Change-as-Code as a framework for governing external system evolution explicitly — not implicitly through deploy side effects.
4. The Mental Model
The mental model of system evolution
Stateful systems are shaped by accumulated change — not snapshots. If the path shapes behavior, the path must be intentional.
5. The Missing Layer
The missing execution layer in system evolution
If behavior depends on ordered cross-boundary change, what enforces that order at runtime? This post introduces the execution layer as a missing architectural capability — through a real incident where identical configuration produced divergent behavior across regions.
6. The Requirements
Structural requirements of an execution layer
If such a layer exists, what must it guarantee? Not aspirationally — as architectural commitments that hold under real conditions. The requirements fall into three categories: what the layer must enforce (deterministic ordering, convergence verification, selective lockstep), what it must remember (a durable evolution ledger, auditability by design), and what it must survive (asymmetric failure, out-of-band change). Remove any single guarantee, and the others degrade.
7. The Execution Models
Execution models for an evolution layer
Human orchestration, pipeline execution, and central orchestration each improve on the last — and each breaks on the same constraint: deterministic evolution across boundaries without sacrificing autonomy within them. The post introduces the declared change graph as the structural alternative to imperative scripts, where evolution becomes a runtime concern rather than a deployment concern.
8. The Architecture
Where the execution layer lives
The execution layer belongs in the runtime — not the delivery path. Like database transactions, the ordering guarantees only matter if they're evaluated against the state the system is actually reaching. Runtime placement changes how governance works (teams declare, infrastructure enforces), how failure recovery works (query the ledger, not reconstruct from logs), and how external boundaries are observed (effects, not commands).
9. The Interface
Expressing system evolution as code
When a domain model change touches the database, Kafka, the REST API, and the API gateway, application teams need a way to execute those changes in order — as a single declared sequence. This post shows what that looks like in practice: ordered Java @Change classes that execute at application startup in lockstep across distributed instances. Failed steps resume. Completed steps never replay. For large migrations that can't block startup, the same sequence runs via CLI. The evolution path sits in the PR alongside the code — making operational risk visible during review rather than during deployment.
10. The Engine (Next)
The interface is defined. The next question is how the execution layer implements it internally — how it coordinates across distributed nodes, handles mid-sequence failure, and maintains the evolution ledger. This is where the architecture of the engine itself comes into focus.