Migrate a source that is not changing
If nothing writes to the source during the migration, there is nothing to catch up on. This is the cheapest path and the one with the fewest moving parts — as long as the claim is true.
When it applies
Section titled “When it applies”- A table loaded in batches, and you are running between loads.
- A read replica or a restored snapshot.
- A table behind a feature flag you turned off.
- A maintenance window in which writes are stopped.
It does not apply to a table that is merely quiet. “Nothing has written for an hour” is not the same as “nothing will write”, and the difference is a row that silently keeps a vector computed from text it no longer has.
The specification
Section titled “The specification”source: mutable: falseconsistency: mode: immutableNo triggers are installed, no companion table is created, and no catch-up is needed.
Run it
Section titled “Run it”ptah inference prepare --spec spec.yaml --db-url "$DB" --run-id "$RUN"ptah inference backfill --spec spec.yaml --db-url "$DB" --run-id "$RUN"ptah inference index --spec spec.yaml --db-url "$DB" --run-id "$RUN"ptah inference verify --spec spec.yaml --db-url "$DB" --run-id "$RUN"catchup is not in the sequence. Running it against this mode is refused rather
than reported as success:
error: catch-up needs a consistency mode that records changes, and thisspecification selects "immutable"That refusal is deliberate. A catch-up that “succeeded” over a mode recording nothing would be a run reporting itself caught up on a source it never watched.
What Ptah checks about the claim
Section titled “What Ptah checks about the claim”plan says what the mode means before anything runs:
Consistency mode: immutable - this requires writes to be paused for the duration, and the run refuses to declare itself ready if they are notVerification’s freshness layer is what catches a broken promise: a row whose source version moved after its vector was computed is reported. If writes happened during the backfill despite the declaration, that is where it surfaces.
What Ptah cannot do is prevent the writes. mutable: false is your statement
about your system, and Ptah takes it and then measures the result.
If writes turn out to have happened
Section titled “If writes turn out to have happened”You have three options, in increasing cost:
- Re-run the backfill. It is resumable and it re-embeds what changed only
if your
version_strategycan see the change. Withinput_hashit can. - Switch the specification to
outboxand start over. The generation identity does not include the consistency mode, so this does not invalidate the vectors already written — but the boundary and the triggers have to be installed by a freshprepare. - Stop the writes properly and repeat.
The second is what most people want after discovering the source was not as paused as they thought.