Upgrades & state
An upgrade replaces an app’s code and keeps its state. The upgrade is an entry in the app’s own log; from that index on, every replica runs the new component against the state the old one wrote (Upgrades & migrations covers who may upgrade and organization-wide upgrade runs).
Keep the state readable
Section titled “Keep the state readable”State lives under keys derived from the #[app::state] field names and the
table and record layouts (Tables & Collections):
- Safe: new methods; new events and errors; new fields on the state struct (a new field is a new key range, empty until written); new tables; new indexes on a new table.
- Not safe: renaming a state field (its old data is left under the old name), changing a field’s collection type or value type, or changing a record’s key, fields or field types. Old rows would no longer decode as the new type.
When a shape has to change, add a new field or table beside the old one, write new data there, and read the old one until it is empty.
The state version
Section titled “The state version”#[app::state(version = N)] records N in the app’s ABI, so clients and the
node’s upgrade gate can tell which state layout a bundle expects. Bump it when
the state’s shape changes.
Test it against the shipped release
Section titled “Test it against the shipped release”Keep each release’s signed .mpk beside the crate and run a migration
scenario from it to the build under test: the steps before its
{ "op": "upgrade" } write state with the shipped code, the steps after read
it with the new code (Testing apps).
Ship v2 of your app walks through a release end to end:
the state change, the test, publishing, and upgrading one instance and then an
organization, with what to do about each refusal.