Skip to content

Commit ff1fe2c

Browse files
dmealingclaude
andcommitted
docs(adr): ADR-0015 — correct the apply story (homegrown runner is net-new)
Honest correction after tracing migrate-ts: for Postgres/SQLite the CLI only GENERATES timestamped append-only up.sql/down.sql — there is no apply runner and no history/schema_migrations journal (only D1→wrangler and the test harness apply today). So the zero-dep homegrown apply+history runner is net-new work the consolidation must build, not "retained." Data migrations work at the file level (append-only survives regen; schema diff doesn't fight hand-added DML) but applied-for-you needs that runner (or an external one), and a data migration's down is hand-authored. Added the runner to the pending realization list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6c9e516 commit ff1fe2c

1 file changed

Lines changed: 29 additions & 11 deletions

File tree

spec/decisions/ADR-0015-single-shared-migrate-engine.md

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,29 @@ which a **dev-time CLI** is not.
4444
MetaObjects owns the **declarative schema diff** (metadata → expected, introspect → actual, diff →
4545
DDL). **Apply, history, and data migrations are a separate, pluggable layer.**
4646

47-
### 2. Two apply modes
48-
- **Built-in homegrown apply** (today's `up.sql` / `down.sql` + direct apply) — retained as the
49-
**zero-dependency default**. It needs no external runner and, notably, gives **free rollback**
50-
via `down.sql` — which **Flyway Community does not** (Flyway's undo/`U__` is a paid Teams/Enterprise
51-
feature). The engine has both schemas, so it generates up **and** down by diffing both directions.
52-
- **Generate** — emit reviewable, **versioned SQL migration files** for an external runner. The
53-
production path for shops standardized on a runner.
47+
### 2. Generation today; a homegrown apply runner is net-new work
48+
49+
**Current reality (do not overstate):** `migrate-ts` **generates** timestamped, append-only
50+
`<ts>-<slug>/up.sql` + `down.sql` (the engine has both schemas, so it emits up **and** down by
51+
diffing both directions). It does **not** apply them for Postgres/SQLite and has **no history /
52+
`schema_migrations` journal** — the only apply paths that exist are **D1 → `wrangler` (external,
53+
with history)** and the **test harness** (`executeSql`). So "the engine picks up and applies your
54+
migration" is **not true today** for Postgres/SQLite.
55+
56+
**Decision — two apply modes, one of them to be built:**
57+
- **Built-in homegrown apply** — a **zero-dependency** runner that applies pending append-only
58+
migrations and tracks them in a journal table, giving **free rollback** via `down.sql` (which
59+
**Flyway Community does not** — undo/`U__` is paid Teams/Enterprise). **This runner is net-new work
60+
for Postgres/SQLite** (only D1/Wrangler + the harness apply today); the consolidation builds it.
61+
- **Generate** — emit reviewable, **versioned SQL migration files** for an external runner
62+
(Flyway/dbmate/…); the production path for shops standardized on a runner.
63+
64+
**Data migrations work at the file level today** (append-only dirs survive regen; the schema diff
65+
never fights hand-added DML), but: (a) "applied for you" depends on the homegrown runner above or an
66+
external runner; (b) the **`down` of a data migration is hand-authored** — the engine auto-reverses
67+
*schema*, not data DML (as with Django `RunPython` reverse / Alembic `downgrade`); (c) ordering a
68+
data migration after the schema it depends on is the author's responsibility (handled by the
69+
timestamp).
5470

5571
### 3. Runner output is a thin adapter layer; Flyway is the reference
5672
The engine generates the up+down SQL **once**; pluggable **output-format adapters** name/lay it out
@@ -162,10 +178,12 @@ delegation) only once the shared engine passes that port's scenarios.
162178
## Realization status
163179

164180
- **Decided:** the strategy above.
165-
- **Pending (staged consolidation plan):** the generate/versioned-file emit + Flyway-naming output;
166-
the `bun --compile` binary; the migrate-conformance / runtime-conformance corpus split; per-port
167-
cutover onto the shared engine; retiring the legacy engines. `field.uuid` / `@dbColumnType` (R6 Plan
168-
2) implemented in the shared engine + the per-port logical/codegen parts.
181+
- **Pending (staged consolidation plan):** the **homegrown apply + journal/history runner** for
182+
Postgres/SQLite (net-new — only D1/Wrangler + the harness apply today); the runner output-format
183+
adapters (Flyway-prefix / two-file / single-file-divider); the `bun --compile` binary; the
184+
migrate-conformance / runtime-conformance corpus split; per-port cutover onto the shared engine;
185+
retiring the legacy engines. `field.uuid` / `@dbColumnType` (R6 Plan 2) implemented in the shared
186+
engine + the per-port logical/codegen parts.
169187

170188
## Conformance note
171189

0 commit comments

Comments
 (0)