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.