Upgrade and Rollback
Upgrade or roll back a self-managed ObjectOS deployment by changing the exact image it pins, after backing up the database — and the operator steps each ObjectStack release asks for.
An upgrade is a change of the exact image you pin, and a rollback is the previous one. On Community that is the image's exact version tag, and its digest if you pin one: the tag can be pushed again onto new bytes when that version is rebuilt, a digest never moves (see Docker → Pin the image). On Enterprise it is the digest your release notes name (Enterprise adds). Everything else on this page is the same for both. Docker → Upgrade and rollback documents the procedure and the reason for each step; this page repeats it as a checklist, and adds the steps particular releases ask for.
Upgrade
- Read the notes of every ObjectStack release between the version you run and the one you are moving to, and work through its version-specific steps below. A major-version move means breaking changes underneath.
- Back up the database. Schema migrations are forward: rolling the image back does not roll the schema back.
- Change the image to the new exact version, or to its digest if you pin
one, and restart. The schema is brought up to date before the runtime
reports ready; a destructive change refuses the boot and names itself
until you apply it with
os migrate apply --allow-destructive. - Confirm readiness (
/api/v1/ready) returns 200.
Roll back
Keep the previous version, and its digest if you pin one: that is what a rollback is. To roll back, restore it and repeat step 3 — valid as long as the version you are leaving made no incompatible schema change (the release notes say when it did). Secrets have the same one-way edge: a secret set or rotated on ObjectStack 17.7 or later cannot be read by a release before 17.7 (see 17.7 below).
The app versions separately
The app itself, when it is delivered as a published artifact, versions independently of the image — see Deployment → How the app gets in. Treat published artifacts as immutable: if you overwrite one in place, you lose the ability to roll back cleanly even when the database backup is perfect (Backup → Artifact versioning).
Version-specific steps
The steps above are the same for every release. Some ObjectStack releases underneath ObjectOS also ask the operator to act: set a variable before the new image boots, run a data migration, rotate a credential. The Community image's version is the ObjectStack version; on Enterprise, the image's release manifest says which ObjectStack version it embeds. Work through the subsection of every version you cross, oldest first, beside the steps above.
Each subsection is the operator's share of that release's upgrade
checklist and links the whole checklist; what a release changes for the app
you run (its metadata and its code) is in the same checklist and in the
Changelog. The os migrate commands are the
ObjectStack CLI at the version the new image embeds. They boot the app to
read its metadata, so run them with the environment the deployment boots
with — the same database and the same app — see
CLI → Database migrations.
Rehearse on a copy. The release notes mark most checklist lines not exercised: derived from the change, not from a walked upgrade. Run each step against a copy of the database first, and back up before the real one.
ObjectStack 17.0
- Run the two data migrations.
os migrate files-to-references, then again with--apply; andos migrate value-shapes, then--applyonce it reports nothing. Until each has recorded its flag, a database created before 17.0 keeps accepting malformed file and reference values with a warning; after, it refuses them. For an integration you cannot fix in time, see the escape hatches. - Every datasource the app binds must connect. One that cannot fails
the boot, and
/api/v1/readyanswers503while one stops answering.
Full checklist: 17.0.0.
ObjectStack 17.1
- Before upgrading, list the permission sets and positions switched
off (
active: false). From 17.1 they stop granting, and a sharing rule that names a deactivated position has its shares revoked. Re-activate the ones still meant to grant. - Re-mint API keys under
isolated. Keys minted before 17.1 carry no organization and are refused underOS_TENANCY_POSTURE=isolated. - Export is granted per object. The shipped administrator permission
sets no longer export every object; grant
allowExportin the app's own permission set where export is intended.
Full checklist: 17.1.0.
ObjectStack 17.2
- Re-point monitoring keyed on
http_request_errors_total. The series is retired and reads a flat zero, which looks like a healthy server. Usehttp_requests_total{status=~"5.."}. - Grant
manage_platform_settingsormanage_metadatato any credential that calls the external-datasource routes; they now refuse other callers403.
Full checklist: 17.2.0.
ObjectStack 17.3
- Walled posture: set
OS_PLATFORM_OWNER_EMAILbefore the new image boots, or it refuses to start. See Environment Variables. - Deduplicate auto-numbers before the new unique indexes can build. Run
os migrate duplicates, fix the duplicates it reports, then re-runos migrate plan. Until you do, the index is not built and the uniqueness is not enforced; the boot only logs it, so a clean boot is not evidence that the index exists. - Backfill
sys_record_share. Sharing grants written before 17.3 carry no organization, and a tenant-scoped read stops finding them. ObjectStack ships the backfill as two functions of@objectstack/plugin-sharing—planSysRecordShareOrganizationBackfill(a dry run) andrunSysRecordShareOrganizationBackfill— not as anoscommand, and nothing runs it at boot. - Open sign-up must now be declared. An app that declares no audience
posture is invite-only: a self-registration is refused
403 SELF_REGISTRATION_CLOSEDunless the address holds a pending invitation (the first account on a fresh install is exempt).
Full checklist: 17.3.0.
ObjectStack 17.4
- Under
isolated, re-mint API keys that carry no organization. They move from200to401. Undergroupsuch a key still works. - Expect
503from the storage download and settings routes while the authorization store is unreachable, where they used to degrade quietly.
Full checklist: 17.4.0.
ObjectStack 17.5
Before you upgrade:
- Walled posture: list every platform administrator in
OS_PLATFORM_OWNER_EMAIL(comma-separated, verified addresses). Anadmin_full_accessgrant stops conferring the standing, and a deployment with no declaration comes up with no platform administrator. - Decide about scheduled work. Time-triggered flows and packaged cron
jobs stop running unless the deployment sets
OS_AUTOMATION_SCHEDULED_WORK_ENABLED=true. Underisolated, first give each scheduled flow's start node theorganizationit runs as, and drain its suspended runs. See Flows. - Pre-flight the account-identity change. Run
os migrate account-issuer(read-only; it exits non-zero while two accounts would collide) and resolve every collision it reports: colliding rows are never merged for you.
Getting onto the release:
os migrate account-issuer # expect: safe to drop
os migrate plan # read every destructive change first
os migrate apply --allow-destructive # drops sys_account.issuer, after a backup
os migrate account-issuer # again: expect zero collisions--allow-destructive applies every destructive change the plan lists, not
only this one — which is why the plan comes first.
After it:
- An anonymous
GET /api/v1/auth/get-sessionanswers401, no longer200withnull. - Analytics refuses
403a caller who cannot read the object. - Failed notification deliveries are kept 7 days, not 90.
Full checklist: 17.5.0.
ObjectStack 17.6
- Hold the upgrade if the app declares an anonymous endpoint
(
authRequired: false) that reads or writes objects. From 17.6 it is refused every object, and no supported channel grants anonymous callers a permission set, in 17.7 either. Public forms are a separate door and keep working. - Grant
manage_platform_settingsto every user or integration that readsdatasourceorexternal_catalogmetadata, or savesdatasourcemetadata, through/api/v1/meta. - Find stored flows that share a packaged flow's name (the startup log warns about each). From 17.6 the packaged flow wins and the stored one stops running; clone the one you need under a new name.
- Rewrite the copies of metadata bodies at rest:
os migrate audit-metadata-bodies, then again with--apply. ⚠️ On 17.6.0 even the dry run writes to the database — run it against a copy. - Find
datetimevalues before the year 1000 and rewrite them; after the upgrade, any write that carries one is refused.
Full checklist: 17.6.0.
ObjectStack 17.7
Before you upgrade:
- Run any conversion that reads a retired field's leftover column while
that field is still declared. After the upgrade no runtime door returns
the column; only
os migrate unmapped-columns --object NAMEreads it. - Add
sharing.enabled: trueto every public form that must stay public, in the app and in stored overlays. Without it the form answers404 FORM_NOT_FOUND. - If you may need to roll back past 17.7, keep a way to set every secret again. A secret set, rotated or re-sealed on 17.7 is written in a format an earlier release cannot open.
- Replace an in-memory boot store (
OS_DATABASE_DRIVER=memory, or amemory://URL): it is refused.
Getting onto the release: run os migrate audit-metadata-bodies, then
again with --apply, to drop the stored content hashes from the audit and
activity copies. The 17.7 dry run no longer writes. A metadata version
token held from before the upgrade answers 409 METADATA_CONFLICT once;
read the item again for a fresh one.
After the first boot:
- Rotate every flow secret — an inbound hook's
secretand anhttpnode'ssigningSecret— once the boot log reports it moved intosys_flow_credential, and hand the new value to whoever signs or verifies. - Rotate the JWT signing keys, and revoke and re-mint the share links that must stay private. Their earlier values may have copies in the audit trail, which the upgrade does not rewrite. How you rotate the signing keys depends on how your deployment supplies them, so follow your deployment's own procedure.
- Resume, cancel or purge flow runs paused before the upgrade. Their stored variables still hold credentials in clear.
- Optional, and only once you will not roll back past 17.7:
os secret rewrap, then again with--apply, re-seals older secrets in the new format. Nothing on the upgrade path runs it. - Drop the retired Localization keys from any client that writes
/api/settings/localization:date_format,time_format,number_format,first_day_of_week. A request naming one is refused400whole. - External sign-in to an unverified local email address is refused
(
account_not_linked); it no longer links to that account silently.
Full checklist: 17.7.0.
Enterprise adds
The Enterprise image is pinned by digest, never by a tag, so an upgrade is a change of digest and a rollback is the previous one.
- Take the new digest from the release notes and read the image's release manifest before rolling it out: confirm the product major line is the one you are on, and check whether the embedded runtime's compatibility range moved.
- Back up the database, then change the image digest and restart the stack. The migration runs to completion before new replicas take traffic.
- Confirm readiness returns 200 and the replicas report healthy. Keep the previous digest to roll back to.
- Kubernetes — upgrading is the same change of image digest, with the migration Job running to completion before the new replicas serve. See Kubernetes → Rolling upgrades change the digest.
- Air-gapped — verify the new digest outside, transfer it in, change the pinned digest, restart. Keep the previous digest: inside an air-gapped network it may be the only copy you have to roll back to. See Air-gapped → Getting the image inside the network.