Skip to main content
Migration Guide

Odoo Migration Guide — Version Upgrades, Data Migration & Platform Moves

Everything you need to upgrade Odoo versions, move between hosting platforms, migrate data from other ERPs, and transfer databases between servers. Practical steps, real commands, and tested workflows.

18-22 min read
Updated February 2026
Odoo 14.0 - 19.0

1Types of Odoo Migration

"Odoo migration" means different things depending on your situation. Before diving into specifics, identify which type of migration you need. Most projects involve one or two of these simultaneously.

Version Upgrade

Moving from one Odoo release to another (e.g., 17.0 to 18.0, or 16.0 to 19.0). Involves database schema changes, module updates, and API adjustments.

Platform Migration

Moving from one hosting platform to another (Odoo.sh to self-hosted, AWS to Hetzner, or any cloud-to-cloud transfer). Same Odoo version, different infrastructure.

Data Migration

Importing data from another ERP system (SAP, QuickBooks, ERPNext, Sage) into Odoo. Requires data mapping, transformation, and validation.

Database Migration

Moving or upgrading the PostgreSQL database itself: server moves, PostgreSQL version upgrades (14 to 16), or cross-region transfers.

Module Migration

Updating custom or third-party modules to work with a new Odoo version. Often the most time-consuming part of a version upgrade, especially with heavy OWL or web framework customizations.

The rest of this guide covers each type in detail with specific commands, timelines, and gotchas. If you are doing a version upgrade and a platform move at the same time, handle them separately: upgrade first on your current platform, verify everything works, then move to the new platform.

2Odoo Version Migration (17 → 18 → 19)

Odoo releases a new major version every year. Each release brings new features, UI improvements, and API changes. As of early 2026, the active versions are Odoo 18 LTS (the current long-term support release) and Odoo 19 (the latest release). Versions 16.0 and earlier are end-of-life for official support.

Version Lifecycle

VersionReleaseStatusPostgreSQL
Odoo 16.0Oct 2022End of Life12 - 15
Odoo 17.0Nov 2023Maintenance12 - 16
Odoo 18.0Oct 2024LTS (Active)14 - 16
Odoo 19.0Oct 2025Latest14 - 17

What Changes Between Versions

Every major version update touches three areas: the database schema (table structures, new fields, renamed columns), the Python API (method signatures, deprecated functions, new decorators), and the web framework (OWL components, JavaScript assets, template syntax). Standard Odoo modules handle these changes through migration scripts. Custom modules need manual updates.

Pre-Migration Checklist

1
Document all installed modules (standard, OCA, custom, third-party)
2
Record your current Odoo version and PostgreSQL version
3
List all custom Python code, JavaScript, and QWeb templates
4
Check if your custom modules have migration scripts for the target version
5
Verify OCA module availability for the target version at github.com/OCA
6
Take a full backup: database (pg_dump) + filestore + configuration files
7
Estimate database size and plan for adequate disk space on the staging server

The Upgrade Process

There are three main approaches to upgrading an Odoo database:

AOdoo's Official Upgrade Service

Available at upgrade.odoo.com. Upload your database dump, select the target version, and the service returns an upgraded database. Handles all standard and Enterprise module migrations. Requires an active Odoo Enterprise subscription. Supports direct jumps (e.g., 14.0 straight to 18.0).

Using Odoo's Official Upgrade Servicebash
# Step 1: Create database dump
pg_dump -Fc -f odoo_production.dump odoo_production
# Step 2: Upload to upgrade.odoo.com (via web UI or API)
# API example:
curl -F "db=@odoo_production.dump" \
-F "contract=YOUR_CONTRACT_NUMBER" \
-F "target=18.0" \
-F "aim=production" \
https://upgrade.odoo.com/database/v1/upload
# Step 3: Download the upgraded database when ready
# Step 4: Restore locally for testing
pg_restore -d odoo_staging --no-owner odoo_upgraded.dump

BOCA OpenUpgrade

Open-source migration framework from the Odoo Community Association. Best for Community Edition users without an Enterprise subscription. Supports sequential upgrades only (17.0 to 18.0, not 16.0 to 18.0 directly). Requires more technical knowledge but gives full control over the process.

OCA OpenUpgradebash
# Clone OpenUpgrade for target version
git clone https://github.com/OCA/OpenUpgrade.git --branch 18.0 --depth 1
cd OpenUpgrade
# Install dependencies
pip install -r requirements.txt
# Run the migration (point to your 17.0 database)
python odoo-bin -d odoo_production \
--update=all \
--stop-after-init \
--load=base,web,openupgrade_framework \
--addons-path=addons,odoo/addons

CManual Migration

Writing your own migration scripts. Only recommended if you have very specific data transformation needs that neither the official service nor OpenUpgrade handles. This is the hardest path and only makes sense for developers with deep Odoo internals knowledge.

Post-Migration Testing

After upgrading the database, run these verification steps on your staging environment before touching production:

  • Start Odoo with --update=all --stop-after-init to verify all modules load without errors
  • Log in and check each installed module's settings page
  • Run through critical business workflows: create a sales order, confirm it, generate an invoice, register payment
  • Check that reports (PDF invoices, delivery slips) render correctly
  • Verify scheduled actions (cron jobs) are configured and running
  • Spot-check data: compare record counts, random invoice totals, and inventory quantities against the source
  • Test user permissions. Different user roles should still have correct access

Budget extra time for custom modules

The official upgrade service and OpenUpgrade handle standard modules. Custom modules (anything in your private addons) need separate migration work. Expect 2-8 hours per custom module depending on complexity.

3Migrate from Odoo.sh

Odoo.sh is Odoo's managed platform. It works well for getting started, but many companies eventually outgrow it due to pricing ($50+/user/month adds up fast), limited server configuration options, and dependency on a single vendor for infrastructure. Moving to self-hosted or a platform like OEC.sh gives you full control over your stack, your costs, and your data.

For a detailed comparison, see OEC.sh vs Odoo.sh. For a step-by-step walkthrough with screenshots, check the dedicated Migrate from Odoo.sh page.

Step-by-Step: Odoo.sh to Self-Hosted

Step 1: Export Your Database

In your Odoo.sh project dashboard, go to Backups, select the production branch, and download the latest backup. This gives you a .zip file containing the database dump and filestore.

Alternatively, use the Odoo.sh shell to create a manual dump:

Export database from Odoo.shbash
# From Odoo.sh shell (SSH)
pg_dump -Fc -f /tmp/production_backup.dump $PGDATABASE
# Download via SCP (from your local machine)
scp your-project@odoo.sh:/tmp/production_backup.dump ./

Step 2: Export the Filestore

The filestore contains all uploaded attachments, images, and documents. If your backup download included it, skip this step. Otherwise:

Export filestore from Odoo.shbash
# From Odoo.sh shell
tar -czf /tmp/filestore_backup.tar.gz /home/odoo/data/filestore/
# Download from your local machine
scp your-project@odoo.sh:/tmp/filestore_backup.tar.gz ./

Step 3: Deploy on Your New Platform

Set up a fresh Odoo instance on your target server. Match the Odoo version and module set exactly. Then restore:

Restore on new serverbash
# On your new server: stop Odoo
sudo systemctl stop odoo
# Drop the empty database and restore from backup
sudo -u postgres dropdb odoo_production
sudo -u postgres pg_restore -d odoo_production --no-owner production_backup.dump
# Extract filestore
sudo tar -xzf filestore_backup.tar.gz -C /opt/odoo/.local/share/Odoo/filestore/
sudo chown -R odoo:odoo /opt/odoo/.local/share/Odoo/filestore/
# Start Odoo
sudo systemctl start odoo

Step 4: Verify and Switch

Log in to your new instance. Check that all data is present, attachments load correctly, and modules work as expected. Update your DNS records to point to the new server. If you use a custom domain on Odoo.sh, remove it from the Odoo.sh project before adding it to your new server's Nginx or Caddy configuration.

Downtime Expectations

For a clean cut-over, plan for 1-4 hours of downtime depending on your database size. A 5 GB database takes roughly 15-30 minutes to dump and 15-30 minutes to restore. The rest is DNS propagation (use a low TTL ahead of time) and verification. If you need near-zero downtime, set up the new server in advance, do a preliminary sync, then do a final incremental sync during a short maintenance window.

Community to Hosted?

If you are moving from Odoo Community self-hosted to a managed platform, the process is similar. See our migration guide for specific instructions.

4Data Migration from Other ERPs

Switching from SAP, QuickBooks, ERPNext, Sage, or another system to Odoo is a different challenge than version upgrades. There is no automatic migration tool because every source system stores data differently. The general approach is: export data from the old system, transform it into Odoo's expected format, then import it.

General Migration Approach

1

Map Your Data

Create a spreadsheet mapping source fields to Odoo fields. Identify which data goes where: customers become res.partner, products become product.template, invoices become account.move, etc. This is the most important step. Get this wrong and everything downstream breaks.

2

Export from Source System

Export as CSV or XML. Most ERPs have bulk export functionality. For QuickBooks, use the IIF or CSV export. For SAP, export via SE16 transactions or ABAP reports. For ERPNext, use the Data Export tool or direct MariaDB queries.

3

Transform and Clean

Use Python scripts or spreadsheet formulas to transform data into Odoo's import format. Handle encoding issues (UTF-8), date format conversions, currency formatting, and reference field mapping. Deduplicate records. This step usually takes the longest.

4

Import into Odoo

Three import methods, from simplest to most powerful:

CSV Import (Built-in)

Odoo's built-in import tool handles CSV files up to ~50,000 records well. Go to any list view, click Favorites > Import Records. Good for contacts, products, and simple records. Not ideal for complex relational data like multi-line invoices.

XML-RPC / JSON-RPC API

For large or complex imports, write a Python script that uses Odoo's external API. This gives you full control over record creation order, error handling, and relational links.

Python XML-RPC import examplepython
# Example: Import contacts via XML-RPC
import xmlrpc.client
url = "https://your-odoo.example.com"
db = "odoo_production"
uid = 2 # admin user ID
password = "your-api-key"
models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")
# Create a partner
partner_id = models.execute_kw(db, uid, password,
'res.partner', 'create', [{
'name': 'Acme Corp',
'email': 'info@acme.com',
'phone': '+1-555-0100',
'is_company': True,
'customer_rank': 1,
}])
print(f"Created partner ID: {partner_id}")

Direct SQL (Advanced)

For very large datasets (millions of records), direct PostgreSQL inserts are the fastest method. This bypasses Odoo's ORM, so you need to handle sequences, computed fields, and audit columns manually. Only use this if you know exactly what you are doing, because incorrect direct SQL can corrupt your database.

Source-Specific Tips

QuickBooks to Odoo

Export Chart of Accounts, Customers, Vendors, Items, and open invoices as CSV. QuickBooks uses different account type naming, so you need to map "Accounts Receivable" to Odoo's receivable type, "Cost of Goods Sold" to expense, etc. Import order: Chart of Accounts first, then partners, then products, then journal entries.

SAP to Odoo

SAP exports tend to be massive and use SAP-specific codes. Focus on master data first (materials, vendors, customers), then transactional data (open POs, open SOs, open invoices). Closed/historical transactions are often left in SAP as an archive rather than migrated. Use SAP transaction codes SE16 or SQVI for exports.

ERPNext to Odoo

ERPNext's data model is closer to Odoo's than SAP or QuickBooks, which makes mapping easier. Export via ERPNext's Data Export tool or query MariaDB/MySQL directly. Key differences: ERPNext uses "DocTypes" where Odoo uses models, and ERPNext stores amounts differently for multi-currency transactions.

Do not migrate everything

A common mistake is trying to import 10 years of closed transactions. For most businesses, migrating master data (contacts, products, chart of accounts) plus open transactions and opening balances is enough. Archive old data in the source system for reference.

5Database Migration

Database migration covers two scenarios: moving a PostgreSQL database between servers (same version), and upgrading PostgreSQL itself (e.g., 14 to 16). Both are straightforward with the right approach. For backup fundamentals, see the Odoo Backup and Recovery Guide.

Moving PostgreSQL Between Servers

The standard pg_dump/pg_restore workflow works for any server-to-server move, whether you are going from AWS to Hetzner, switching VPS providers, or moving to a dedicated database server.

Move database between serversbash
# On the source server: create a compressed dump
pg_dump -Fc -Z 5 -f /tmp/odoo_dump.backup odoo_production
# Transfer to destination server
rsync -avz --progress /tmp/odoo_dump.backup user@new-server:/tmp/
# On the destination server: create database and restore
sudo -u postgres createdb -O odoo odoo_production
sudo -u postgres pg_restore -d odoo_production --no-owner --role=odoo /tmp/odoo_dump.backup
# Don't forget the filestore
rsync -avz /opt/odoo/.local/share/Odoo/filestore/ user@new-server:/opt/odoo/.local/share/Odoo/filestore/

Upgrading PostgreSQL (14 → 15 → 16)

When upgrading PostgreSQL on the same server, you have two options: pg_upgrade (in-place, faster) or dump-and-restore (safer, works across machines). For Odoo databases, dump-and-restore is recommended because it reindexes everything and avoids compatibility quirks.

Upgrade PostgreSQL versionbash
# Step 1: Install new PostgreSQL version alongside the old one
sudo apt install postgresql-16
# Step 2: Dump from old version
sudo -u postgres /usr/lib/postgresql/14/bin/pg_dump -Fc odoo_production > /tmp/odoo_pg14.dump
# Step 3: Stop old PostgreSQL, start new one
sudo systemctl stop postgresql@14-main
sudo systemctl start postgresql@16-main
# Step 4: Create role and database on new version
sudo -u postgres createuser -s odoo 2>/dev/null || true
sudo -u postgres createdb -O odoo odoo_production
# Step 5: Restore into new version
sudo -u postgres pg_restore -d odoo_production --no-owner /tmp/odoo_pg14.dump
# Step 6: Update Odoo config if the port changed
# Check /etc/postgresql/16/main/postgresql.conf for the port
# Update db_port in /etc/odoo/odoo.conf if needed
# Step 7: Restart Odoo
sudo systemctl restart odoo

Cross-Cloud Migration

Moving between cloud providers (AWS RDS to self-managed, DigitalOcean to Hetzner, etc.) follows the same dump-and-restore pattern. The main considerations are network transfer speed and security:

Encrypted cross-cloud transferbash
# For large databases, compress and encrypt during transfer
pg_dump -Fc -Z 9 odoo_production | gpg --symmetric --cipher-algo AES256 | ssh user@new-server "cat > /tmp/odoo_encrypted.dump.gpg"
# On the new server: decrypt and restore
gpg --decrypt /tmp/odoo_encrypted.dump.gpg | pg_restore -d odoo_production --no-owner

Check disk space first

You need at least 2x your database size in free disk space on the destination server: one copy for the dump file, one for the restored database. A 10 GB database needs ~20 GB of free space during migration.

6Module Migration

When you upgrade Odoo versions, every custom module needs to be updated for the new release. Standard Odoo modules and OCA modules are handled by the upgrade service and the OCA maintainers respectively. Your private/custom modules are your responsibility. This is often the most labor-intensive part of a version upgrade.

Common API Changes Between Versions

Each Odoo version introduces breaking changes. These are the typical areas that require module updates:

Python API Changes

Deprecated methods get removed, method signatures change, and new decorators appear. For example, Odoo 17 removed several legacy widget types, and Odoo 18 changed how mail.thread mixins handle tracking. Always check the release notes for your target version.

OWL Framework Updates

Odoo's web framework (OWL) has evolved significantly. Odoo 17 moved to OWL 2, and later versions continue to refine the component lifecycle, hook system, and template compilation. Any custom JavaScript components need updates when the OWL version changes.

QWeb Template Changes

Report templates and website snippets use QWeb, which gets updated each version. Field names change, t-call targets move, and CSS class names get updated. Run your reports in staging to catch rendering issues early.

Security & Access Changes

Access control rules, record rules, and ir.model.access entries sometimes change between versions. A module that worked on 17.0 might throw access errors on 18.0 because the base security groups were reorganized.

OCA Module Compatibility

OCA modules are maintained by volunteers and typically get ported to new versions within 3-6 months of release. Check the branch list on the OCA GitHub repository to see if your required modules have been ported. The OCA Modules Guide covers how to find and install OCA modules for any version.

Check OCA module version availabilitybash
# Check if an OCA module has been ported to 18.0
git ls-remote --heads https://github.com/OCA/account-financial-tools.git | grep 18.0
# If the branch exists, clone it
git clone https://github.com/OCA/account-financial-tools.git --branch 18.0 --depth 1

Testing Workflow: Staging → Test → Production

Never test module migrations on production. Use this workflow:

  1. Development: Update the module code on your local machine or dev server. Fix import errors, deprecated API calls, and template issues.
  2. Staging: Deploy the updated module to a staging environment with a copy of production data. Run -u module_name --stop-after-init to verify the upgrade script runs cleanly.
  3. User Acceptance Testing: Have actual users test their workflows on staging. They will catch issues that automated tests miss, like button placement, form flow, and report formatting.
  4. Production: Schedule a maintenance window, take a backup, deploy the updated modules, and run the upgrade.

Write migration scripts

For custom modules with data model changes, create migration scripts in your_module/migrations/18.0.1.0.0/pre-migrate.py and post-migrate.py. These run automatically during the upgrade and handle data transformations, column renames, and computed field recalculations.

7Migration with OEC.sh

OEC.sh has several features that simplify migration, whether you are upgrading versions, switching platforms, or doing both at the same time.

Multi-Project Support

Run your old (17.0) and new (18.0) Odoo instances simultaneously on different projects. Compare data side-by-side, let users test the new version while production stays on the old one. No extra infrastructure to manage, since both projects deploy to your cloud account.

Database Cloning

Clone your production database to a staging environment with one command. Test the upgrade on a real copy of your data without affecting production. Clone again whenever you need a fresh copy for another round of testing.

Automated Backups and Rollback

OEC.sh takes automatic backups before any major operation. If something goes wrong during migration, roll back to a known-good state in minutes instead of hours. Daily backups with 30-day retention provide additional safety.

Staging Environments

Spin up isolated staging environments for migration testing. Each environment gets its own URL, database, and configuration. Deploy the new Odoo version to staging, restore your production backup, run the upgrade, and test, all without touching production.

See OEC.sh Features for the full list of platform capabilities, or check Pricing to find a plan that fits your migration needs.

8Migration Checklist

Use these checklists to track your migration progress. Print them out or copy into your project management tool.

Pre-Migration

Identify migration type (version upgrade, platform move, data import, or combination)
Document current Odoo version, PostgreSQL version, and Python version
List all installed modules with versions (Settings > Technical > Modules)
Identify and list all custom modules and third-party modules
Check custom module compatibility with target version
Check OCA module availability for target version
Measure database size and filestore size
Create full backup (database + filestore + config)
Set up staging environment with target Odoo version
Lower DNS TTL to 300 seconds (5 minutes) at least 48 hours before migration
Notify users of planned maintenance window

During Migration

Enable maintenance mode / notify users system is offline
Take final production backup (database + filestore)
Run database upgrade (official service, OpenUpgrade, or manual)
Deploy updated custom modules to target environment
Run Odoo with --update=all --stop-after-init and check logs for errors
Verify all modules install and load without exceptions
Restore filestore to the correct location with proper permissions
Test login with admin and at least one regular user account

Post-Migration

Test critical workflows: sales order, purchase order, invoice, payment, inventory transfer
Verify PDF reports render correctly (invoices, delivery slips, quotations)
Check that email sending works (outgoing mail server)
Verify scheduled actions (cron jobs) are active and running
Spot-check record counts against source system
Test file attachments and image display
Update DNS records to point to new server (if platform migration)
Monitor error logs for 24-48 hours after go-live
Confirm automated backups are running on new environment
Decommission old server after 1-2 weeks of stable operation

9Frequently Asked Questions

Related Guides

Ready to Migrate Your Odoo?

Deploy Odoo on your own cloud, clone databases for migration testing, and roll back instantly if anything goes wrong. Start free with OEC.sh.

5 min
Deploy Time
1-click
DB Cloning
$0
To Start