Skip to main content
Ready to deploy? Try it free

Documentation Deploy & operate

Version upgrades

An app's Upgrade menu: planning an upgrade to a newer Odoo version as a new app, the readiness checks, runs and migration steps, review and acceptance, the production switch-over and moving URLs. For the namespace's Maintainers and Admins.

Staff Updated 11/12/2026

Version upgrades

The Upgrade menu moves an app's data to a newer Odoo major version, as a new app beside the old one in the same project.

You can

  • Plan a Test, which ends with an upgraded, neutralized copy to try, or a Production upgrade, which then switches over (Plan an upgrade).
  • Move the upgrade on with the buttons beside the stages in the bar. Only those the server allows now are shown.
  • Click a finished stage in the bar to look at it again.
  • Open the same upgrade from either app's Upgrade menu, the old one's or the new one's.

Good to know

  • The old app is never changed: a run only takes an online backup of it, with no maintenance and no stop. Only a production switch-over stops it.
  • Both apps are kept afterwards, and a person decides what happens to each.
  • The menu and its actions are for the namespace's Maintainers and Admins; the server refuses them to everyone else.
  • It needs a plan with Backup Automation (Essential, Pro or Premium), and a deployed old app with no other open upgrade.
  • Customers do see the new app in their project, with a note such as Upgrade test of shop: 18.0 → 19.0.

Apps

The upgrade's two apps, old and new, side by side for the upgrade's whole life.

You can

  • Go to an app's own screen with Open this app, and manage it there with its usual actions.
  • Read the new app's log with Upgrade log: the engine, the module update and the post-migration steps.
  • Read the old app's log with Pre-migration log: the pre-migration steps, run on a copy of its database. It is offered only when the plan has pre-migration steps; nothing else writes there.

Good to know

  • After a switch-over, LIVE marks the app that serves production, and STANDBY the stopped one, which holds a copy of the production data.
  • A simulated upgrade is marked Simulated — not sent to Odoo (Upgrade to).

Plan an upgrade

With no upgrade open, the Upgrade menu shows one card: Plan an upgrade opens the plan, which proposes what an upgrade of this app would be. You set its purpose and server, then plan it, or go Back to the card.

You can

  • Set the Purpose: Test gives a neutralized copy that stays up until someone closes it; Production switches over once a run is accepted.
  • Pick Production server to test on the hardware the app will serve on, so the downtime estimate is real.
  • Pick Staging server to keep the load off production. The downtime estimate is then only indicative.
  • Create the upgrade and the new app with Plan the upgrade, once a target, a database, a name and a branch are set.

Good to know

  • Planning runs nothing and leaves the old app untouched. The new app is not deployed yet.
  • Staging is offered when the project has a deployed staging environment. A staging app's upgrade has only staging.
  • A production upgrade always uses the production server.
  • No branch is needed when the app has no custom repository.
  • Once the upgrade is planned, Plan shows the choices read-only.

Upgrade to

The Odoo version the app upgrades to, and the engine and contract the upgrade goes through.

You can

  • Pick the Target version among those the environment has an image for. Changing it also changes the proposed name, prefix and branches.
  • Press Read database to read the installed modules and the stored contract code. Until then, the app's edition stands in.
  • Leave Subscription code empty to send the one the old database stores, or type another: 6 to 64 letters, digits, - or _.
  • Turn on Simulate (operators, for testing) to run the process here, with OpenUpgrade: nothing is sent to Odoo.

Good to know

  • The Engine is not a choice: the old database decides, and Readiness reads it again before every run.
  • An Enterprise database (web_enterprise installed) goes to the Odoo upgrade service, which upgrades a copy at Odoo. A Community one stays on the platform, with OpenUpgrade.
  • Without a subscription code, an upgrade through Odoo's service cannot run.
  • An upgrade through Odoo's service sends a full copy of the database to Odoo S.A. (Belgium). Its first run asks you to agree; the upgrade records who agreed and when, and a production upgrade made from a test asks again.
  • A simulated run is never accepted for production or switched over: its Enterprise modules come out best effort.
  • Until Odoo's service is enabled on the platform, Readiness blocks every real Enterprise run, so simulation is the only way to run one.

Branches

The branch of each of the old app's repositories that the new app is built from.

You can

  • Pick, for each repository, the branch that holds the code ready for the target version.
  • Press Fetch branches to read a repository again, then Refresh in the note that appears to list its new branches.

Good to know

  • Any branch can be picked. Those named for the target, such as 19.0, come first, and when exactly one is, it is proposed.
  • Pick one branch per repository, and at least one in all.
  • An app with no custom repository has nothing to pick: the new app runs Odoo's own modules only.
  • Before every run, Readiness checks that each picked branch still exists.
  • If a branch moves after a run is accepted, the upgrade asks for a new run or an acknowledgement (Review).

Database

The database instance the new app will run on.

You can

  • Pick one of the deployed instances in the chosen environment or on its server. The environment's own instance is proposed.
  • Pick a newer instance here when the old app runs on one too old for the target (Database instances).
  • Create and deploy an instance first when the server has none.

Good to know

  • Odoo 19.0 needs PostgreSQL 13 or newer, and 20.0 needs 16. An older instance is listed but cannot be picked.
  • The new app gets a database of its own there. The old app's database is never touched.
  • Readiness checks the version again before each run.

New app

The name and prefix of the app the upgrade creates.

You can

  • Change the Name, proposed as the old app's name followed by the target version, such as Shop 19.0.
  • Change the Prefix, proposed as the old prefix followed by the major version, such as shop-v19.

Good to know

  • Changing the target updates both, until you type your own.
  • The prefix is made safe for names on the server, at most 40 characters.
  • The new app is created in the chosen environment when you plan, with its own default URL and its own admin password.
  • Customer domains stay on the old app until someone moves them (Move URLs).

Copied from this app

What the new app takes from the old one, and the four values to check because option and module names change between versions.

You can

  • Review the config patch, additional packages, automated add-ons and excluded add-ons, and change what the new version needs.
  • Check the names under Container variables. Their values are copied without being shown, since they can be secrets.

Good to know

  • Your changes go to the new app only. The old app keeps its own values.
  • Everything else is copied as it is: the edition, workers and limits, container, automation and test settings, auto backup, the note, and more.
  • The URLs (except the new app's own default one), the admin password, backups, restore points, deploy history and logs are not copied.
  • The App editor is not carried over: install it again on the new app, from its Access menu.
  • The version, image and shared addons come from the target version.

Readiness

Readiness runs quick checks before a run and keeps the results. Run the checks in the bar (Check again after the first time) runs them. Run them again whenever something changes. A planned upgrade with no blocker is ready to run. Each check shows ok, warning or blocker, with what it found:

CheckWhat it asks
Target branchesEach picked branch still exists (blocker), and has a known commit (warning).
Database versionThe new app's instance runs the PostgreSQL the target needs.
Disk on the new app's serverFree space on the disk that holds Docker's data, for four times the old database's size (taken from its last backup), and at least 2 GB.
Disk on the old app's serverThe same, only when there are pre-migration steps: they run on a copy there.
Backup storageThe project's off-site storage answers. Having none is a warning: the backups then stay on the servers.
Nothing else runningNo workflow is running on either app.
Workflow safety lockThe lock lets both servers run.
EngineReads the old database's modules again and sets the engine. A database it can't read is a blocker.
Enterprise contractFor Odoo's service: a subscription code, and the service enabled on the platform. A simulation shows a warning instead.
Engine imagesFor OpenUpgrade or a simulation: a base image for every version on the way.
OpenUpgrade coverageFor OpenUpgrade or a simulation: installed modules it does not cover or renames are warnings. A version with no scripts is a blocker, and so are modules a pre-step must uninstall while there is no pre-step.

For Odoo's service, the section also has Subscription code with Save code, and Simulate (operators, for testing). Saving either one runs the checks again.

A blocker stops a run from starting. A run that starts more than ten minutes after the last check runs the checks again first, and a switch-over always does. The checks change nothing on the servers.

Upgrade run

A run upgrades a fresh copy of the old app's data into the new app. Once Readiness has no blocker, Start the upgrade run in the bar starts it (Start another run for later ones). In order, it:

  1. builds the new app on the target version and branches: it deploys the app the first time and updates it after that;
  2. takes an online backup of the old app, with no maintenance and no stop;
  3. runs the pre-migration steps, if any, on a scratch copy of that backup on the old app's server;
  4. upgrades the data with the engine, and keeps the result as an upgraded backup of the new app;
  5. restores it into the new app neutralized, with a new database uuid and a reset admin password, so the copy sends no mail, runs no production crons and claims no subscription;
  6. updates the project's custom modules on the new code, runs the post-migration steps and checks the result;
  7. takes the new app out of maintenance, so the team can try it on its own URL.

The page follows the run live, with one row per workflow, in order, and its runners. Open a runner to see its log or retry it. A run can take hours. If a run fails, the page says why, and it can be resumed from Review.

Starting any run clears an earlier acceptance and any scheduled switch-over. The measured times of the backup, the pre-steps, the engine, the restore and the module update add up to the downtime estimate of a switch-over.

Migration steps

Fixes for the data, written and tried on copies, then applied to the copy of production at the switch-over; production itself is never edited.

You can

  • Add a Pre-migration step: it runs before the engine, on a scratch copy of the old database, with the old app's code.
  • Add a Post-migration step: it runs on the new app's database with the new code, after its custom modules update and before the checks.
  • Write a step in Python, run like the Odoo shell, or in SQL, run as written in one transaction.
  • Reorder a phase's steps with the arrows, or skip a step with Active without deleting it.
  • Try one step now from Review with Run this step: a post-step on the new app, a pre-step on the last run's scratch copy.

Good to know

  • Each step runs in its own transaction and commits when it succeeds. The first failure stops the phase, unless the step says Continue.
  • The code runs as the superuser on a copy of the customer's database, with outgoing mail off: review it as you would their own code.
  • It can use env, env.cr, log, Command, UserError, datetime and time, within a timeout of 1 to 720 minutes.
  • Steps cannot change while a run is going or after the upgrade closed.
  • A change made after a run was accepted needs a new run or an acknowledgement.

Review

When a run ends, the upgrade is under review. The stage's section, Runs, lists every run, newest first. Each shows its kind (Upgrade run, Re-run from pre-steps, Migration re-run, Single step, or a switch-over's runs), its state, when it ran, its input and upgraded backups, and how long each stage took. Open a run to see its workflows, why it failed, and its Modules, Checks and Steps. Above the list are the estimated downtime of a switch-over and who accepted which run.

ButtonWhat it does
Re-run the migrationRestores the stored upgraded copy and updates the custom modules with the branch as it is now. The engine does not run again. Use it to try a fixed migration script or post-step.
Re-run from the pre-stepsRuns again from the pre-migration steps, on the same backup, with no new backup of the old app.
Resume the failed runContinues from the workflow or step that failed. What came before is not run again.
Accept this runRecords who signed off a run that passed its checks. If a branch moved or a step changed since that run, the refusal says what. Run again, or use Accept anyway.
Use for productionOn an accepted test. On the production server, the same upgrade becomes a production upgrade and keeps its runs and estimate. On the staging server, a new production upgrade is created from it, with a new app beside the old one, its own run and its own acceptance; the test is left as it is.
Continue to the switch-overOn an accepted production upgrade: opens Switch over.

A full run on fresh data is started from the Upgrade stage. For a production upgrade, only a real run (not simulated) no older than 14 days can be accepted (deployment.upgrade_accept_max_days). A test ends here: the new app stays up on its own URL until someone finishes the upgrade or deletes the app. Finish the upgrade and Cancel the upgrade are under Finish or cancel.

Modules

What this run's module update found in the upgraded database.

You can

  • Read Missing from the new code: modules the database has installed but the new app has no code for.
  • Add the repository or branch that has a missing module, or uninstall it in a pre-step (Migration steps).
  • Read Custom, updated on the new code: the project's own modules, updated on the target code with their own migration scripts.

Good to know

  • A run that stopped before the module update has no report.
  • A missing module usually also leaves something unmet in Checks.

Checks

The checks made on this run's upgraded database itself, each ticked or crossed.

You can

  • See which checks passed: only a run that passed its checks can be accepted.
  • Fix what failed with a branch push or a step, then press Re-run the migration.

Good to know

  • Database version passes when the database's base version starts with the target version.
  • Modules left to update passes when no module waits to be updated, installed or removed.
  • The other checks ask that modules are installed, the database is not empty, and the module update logged no errors.
  • Re-run the migration restores the stored upgraded copy and updates the custom modules on the branch as it is now; the engine does not run again.

Steps

Each migration step this run ran, with its phase, state and duration.

You can

  • Open a step's log with Show output, with its traceback when it failed.
  • Fix a failed step under Migration steps, then continue from it with Resume the failed run.
  • Try the fixed step alone first with Run this step.

Good to know

  • A failed step opens by itself.
  • Resuming continues from the step that failed. What came before is not run again.
  • A pre-step run alone uses the scratch copy the last run kept; a post-step runs on the new app.

Switch over

A production upgrade's switch-over makes the new app the production app. It is the only stage with downtime. The stage shows the estimated downtime, the accepted run, and a recap of the readiness checks.

Switch over now, in the bar, asks you to type the old app's name. Alternatively, pick a date and time and click Schedule, which asks the same. Clear schedule drops a scheduled switch-over. A scheduled switch-over starts by itself, with the same checks. If it can't start within 30 minutes of its time, it doesn't start late, and the stage says why.

In order: the old app goes into maintenance and stops. A final backup of it is taken and pinned. The pre-migration steps run on a copy, and the engine upgrades it. The new app is held in maintenance and receives the data, not neutralized this time and keeping the database's uuid. Its custom modules are updated, the post-migration steps run and the checks pass. Then the new app starts and leaves maintenance.

The old app is down for the whole window, and its visitors see its maintenance page. Webhooks and mail sent to it during the window may be lost. The switch-over needs an accepted real run no older than 14 days, the same steps and branch heads as at acceptance, and no readiness blocker. If anything fails before the new app starts, the switch-over is undone: the new app stays stopped behind its maintenance page, and the old app is live again on its untouched database. Customer domains stay on the old app until moved (see Move URLs).

Decide

After a switch-over, both apps are kept. Decide shows which app is live and which stands by, and since when. It also shows the old app's final backup, which is pinned so retention never deletes it. From here, what happens to each app is a person's call, made with that app's own actions. The bar offers:

  • Switch back, while the new app is live: type the new app's name. The new app goes into maintenance and stops, then the old app starts and leaves maintenance. Move the URLs back too is ticked by default. Data written in the new app since the switch-over is not carried back, because there is no downgrade; the confirmation says how many hours that is.
  • Switch over again, while the old app is live: repeats the switch-over with fresh data.
  • Move URLs and Finish the upgrade: see below.

The standby app holds a copy of production. Any action that would start it asks you to type its name. This includes Deploy, Update, Restart, Update Config and Disable Maintenance. The prompt warns that mail and scheduled actions would run twice and that two databases would claim one Enterprise subscription. Confirming allows the start for five minutes. A customer is refused that start until upgrades are released.

After both apps have been kept for 14 days (deployment.upgrade_reminder_days), the namespace's Admins and Maintainers get a reminder in the bell and by email. It repeats every week until the upgrade is finished.

Move URLs

Moves custom URLs from one app of the upgrade to the other, once both apps are kept.

You can

  • Pick the way with Direction. By default, the URLs leave the app that is not live.
  • Tick the URLs to move in the first app's list. The receiving app's URLs are listed below it.
  • Press Move, then follow the run under Decide.

Good to know

  • A default URL is listed but never moves.
  • Move attaches the URLs to the receiving app, then applies both apps' configuration again, the app they left first, so the routes follow.
  • The standby app is stopped again after its configuration is applied.
  • Until the URLs are moved after a switch-over, the customer's domains still lead to the old app, stopped behind its maintenance page.
  • Switch back can move the URLs back in the same step.

Finish or cancel

Finish the upgrade closes it, once a run is under review or both apps are kept. It asks which app you kept (see below) and records the answer. It does not stop, close or delete either app: do that with each app's own actions. The runs' scratch copies are cleaned up. The old app's final backup stays pinned until someone deletes it.

Cancel the upgrade abandons it. It is offered before a switch-over, and not while a run is going. The old app was never touched. If nothing ever ran on the new app, the new app is removed along with the plan. Otherwise it stays, with whatever the runs put in it, until someone deletes it.

Neither can be undone. Afterwards, the Upgrade menu offers a new plan, and the plan says how the last upgrade ended.

Which app did you keep?

Which of the two apps you keep, recorded when you finish the upgrade.

You can

  • Pick the app you keep, the old one or the new one, and click Finish.
  • Once nobody needs the other app, put it in maintenance, stop it or delete it from its own screen.

Good to know

  • The choice is recorded on the upgrade only: neither app changes.
  • The other app keeps running, or standing by, until someone acts on it.
  • It holds a full copy of the data. After a switch-over, that copy is production data.
  • Finishing cannot be undone (Finish or cancel).

Was this page helpful?

Your answer helps us prioritize documentation improvements.

Thanks — your feedback helps us improve.