Skip to main content
Migrating Your Odoo Database on Odoo.sh: A Practical Guide
6 min read
Odoo

Migrating Your Odoo Database on Odoo.sh: A Practical Guide

A step-by-step guide to safely upgrading an Odoo database between major versions on Odoo.sh β€” using development and staging branches, the Test Upgrade button, and Odoo's official upgrade platform.

Open Odoo.sh Upgrade Docs

Introduction

Upgrading an Odoo database used to mean dump files, support tickets, and a long window of "please don't touch the system." On Odoo.sh, the entire workflow is built into the platform β€” fork a branch, click Test Upgrade, and the official upgrade.odoo.com service handles the heavy lifting in the background.

But automation only goes so far. If your custom modules aren't compatible with the target version, the upgrade fails. If you skip staging, you risk hours of unplanned downtime. This guide walks through the workflow that actually works in practice β€” the order, the gotchas, and the safety nets.


The Three-Branch Workflow

Every Odoo.sh upgrade follows the same path: Development β†’ Staging β†’ Production. Each branch has a specific role.

text
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚           PRODUCTION (v18)            β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚ fork
                                    β–Ό
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚  1. DEVELOPMENT (v19)                 β”‚
                  β”‚     β€’ Bump Odoo version in settings   β”‚
                  β”‚     β€’ Upgrade your custom modules     β”‚
                  β”‚     β€’ Verify on an empty DB           β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚ drag β†’ staging
                                    β–Ό
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚  2. STAGING (Test Upgrade)            β”‚
                  β”‚     β€’ "Test Upgrade" sends a copy of  β”‚
                  β”‚       production to upgrade.odoo.com  β”‚
                  β”‚     β€’ Restored as the staging DB      β”‚
                  β”‚     β€’ You test on real data           β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚ merge upgraded code
                                    β–Ό
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚  3. PRODUCTION (v19)                  β”‚
                  β”‚     β€’ Auto backup β†’ upgrade β†’ restore β”‚
                  β”‚     β€’ Auto rollback if anything fails β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Each step blocks the next. Do not start a staging Test Upgrade until your custom modules build cleanly on the dev branch, and never push to production until the staging Test Upgrade is green.


Step 1 β€” Prepare a Development Branch

The first job is to make your custom code compatible with the target version. Custom modules are not upgraded by Odoo's upgrade service β€” that part is on you.

  1. In your Odoo.sh dashboard, fork your Production branch into a new Development branch (e.g., upgrade-v19).
  2. Open the branch's Settings, find the Odoo version field, and change it to the target version (e.g., 19.0).
  3. Push code changes that bring each custom module up to the new version's API: deprecated decorators, field syntax, view elements, manifest dependencies.
  4. Wait for the build to go green. The branch now boots on the target Odoo version with an empty database, so startup errors in your custom code surface here first.

Tip: make your custom code work on an empty DB first. If it can't install fresh on v19, it won't survive a real upgrade either.


Step 2 β€” Run "Test Upgrade" on Staging

This is where the actual database migration is tested against real production data β€” but in isolation.

  1. From the Odoo.sh dashboard, drag your development branch into the Staging stage.
  2. Open the new staging branch and go to the Upgrade tab.
  3. Click Test Upgrade and select the target version.
  4. Odoo.sh sends the latest daily production backup to upgrade.odoo.com. The platform upgrades the schema and standard module data, then sends the upgraded dump back, which is auto-restored on your staging branch.
  5. Once the build comes up, check the upgrade log:
bash
tail -n 200 ~/logs/upgrade.log
  1. Resolve every error and warning before continuing.
  2. Test every critical workflow as a real user would: sales orders, invoices, accounting closes, custom reports, integrations. Treat anything weird as a blocker.

Step 3 β€” Promote to Production

Once staging is green and you're confident:

  1. Merge the upgraded code from your staging branch into Production. Make sure the version in __manifest__.py files and the branch settings match the target.
  2. Communicate the maintenance window to users β€” production will be briefly unavailable.
  3. On the production branch's Upgrade tab, click Upgrade.
  4. Odoo.sh takes a backup automatically, sends the production DB to upgrade.odoo.com, and restores the upgraded result in place.
  5. If anything fails, the platform rolls back automatically to the pre-upgrade backup. You're not stranded.

Who Does What

The single biggest source of failed Odoo upgrades is confusion about scope. This is the line:

You handleOdoo.sh / upgrade.odoo.com handles
Updating your custom modules' source codeUpgrading standard module code
Fixing deprecated APIs and view syntaxTransforming the database schema
Pushing version-compatible codeMigrating standard module data
Setting the target version in branch settingsProducing the upgraded dump
Testing business workflows on stagingRestoring the dump on your branch
Approving the production promotionBacking up production before the upgrade
Communicating downtime to usersRolling back automatically on failure

If your upgrade fails, look at the table. The answer is almost always in the left column.


Pitfalls That Cause Real Outages

Skipping intermediate versions. Odoo upgrades version-by-version. A 17 β†’ 19 jump goes through 18 internally. Your custom modules must work on the final target β€” but you don't write intermediate code.

Continuing development during the upgrade. Every new commit on production during the upgrade window means re-testing on staging. Freeze the codebase from the moment Test Upgrade starts.

Ignoring the cascade. A version bump on one module forces upgrades on every dependent module β€” and surfaces dormant deprecation warnings as hard failures. We covered this exact failure mode in Why a Version Bump Breaks Your Odoo.sh Build.

Forgetting third-party modules. OCA or Apps Store modules without a target-version release will block the upgrade entirely. Audit dependencies before starting.

Skipping staging. "It worked in dev" means nothing β€” dev uses an empty database. Test Upgrade against real production data is the only meaningful validation.


Conclusion

Odoo.sh upgrades are best thought of as two parallel tracks: code (yours) and data (Odoo's). The platform handles data transformation, automatic backups, and rollback. You handle making your modules compatible and validating that the business still runs after.

The order matters: dev β†’ staging β†’ production, with a code freeze in between. Skip a step and you'll pay for it in downtime. Follow the workflow and most upgrades land cleanly β€” boring, even.

If you're staring at a failed upgrade.log and not sure where to start, the message you want to find is rarely about the database. It's almost always about a module that wasn't ready.