Schema compatibility¶
Migrations are ordered, immutable, and forward-only. The migrator serializes concurrent runs with an advisory lock, so every process can call it at startup.
Never edit a migration that has reached another environment
The migrator records a checksum. Editing an applied migration makes every database that already ran it refuse to start.
When the protocol changes¶
The storage protocol changes only when a worker cannot safely share the schema with the previous protocol.
Additive tables, columns, indexes, views, and functions do not require a protocol change, because an old worker can ignore them. Reserve the protocol bump for changes that would make an old worker behave incorrectly rather than merely miss a feature.
Check compatibility with the range. Do not compare pgtask.storage_protocol_version() for equality - that is the
current identifier, useful for reporting, not a compatibility test.
What enforces this¶
The rule above is checked rather than trusted.
tests/sql_surface_baseline.txt records the schema as of the oldest storage protocol the release
still supports. A test asserts that every function signature, view, and grant in that baseline still
exists unchanged. Additions pass, because a worker built for the older protocol never calls them.
Removals and changes fail, because that same worker still calls what it always called:
the schema is no longer backward compatible with storage protocol 1
changed function queue_demand(p_queue_name text, ...) -> TABLE(...)
baseline: grants: pgtask_surface_worker=X/{owner}, {owner}=X/{owner}
now: grants: {owner}=X/{owner}
Dropping support is deliberate rather than accidental. Raise STORAGE_PROTOCOL_MIN_VERSION, then
rerun with PGTASK_UPDATE_SQL_BASELINE=1 to rebase the baseline on the new minimum.
Structure is checked, meaning is not
A function that keeps its signature and changes what it does passes this test. That is exactly the change a protocol bump exists for, and it remains a judgement you make rather than one the suite makes for you.
Client access goes through functions and views only, so those signatures and their grants are the whole contract. Table columns are internal and can change freely.
Rolling releases¶
Use expand and contract:
- Add the new shape while the old shape stays valid.
- Deploy workers that understand both.
- Move producers to the new shape.
- Wait until the oldest supported worker is gone.
- Remove the old shape in a later release.
The invariant to hold: one released worker version before and after a migration must run concurrently. If a change cannot preserve that window, stop workers and producers and declare a maintenance release. Discovering that mid-rollout is considerably worse than planning it.
For an incompatible change, expand the database range before deploying new clients, and contract it only after the
old ones are gone. A range like 1..=2 is what keeps both releases working during the overlap.
Retry policies are part of the identity¶
A retry policy belongs to a (queue, task_name, handler_version). The database rejects policy drift under an existing
identity, so changing retries requires a new handler version. See Retries.
For the operational procedure, including what happens to work in flight and how to roll back, see Upgrade pgtask.