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
| Version | Release | Status | PostgreSQL |
|---|---|---|---|
| Odoo 16.0 | Oct 2022 | End of Life | 12 - 15 |
| Odoo 17.0 | Nov 2023 | Maintenance | 12 - 16 |
| Odoo 18.0 | Oct 2024 | LTS (Active) | 14 - 16 |
| Odoo 19.0 | Oct 2025 | Latest | 14 - 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
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).
# Step 1: Create database dumppg_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 testingpg_restore -d odoo_staging --no-owner odoo_upgraded.dumpBOCA 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.
# Clone OpenUpgrade for target versiongit clone https://github.com/OCA/OpenUpgrade.git --branch 18.0 --depth 1cd OpenUpgrade# Install dependenciespip 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/addonsCManual 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-initto 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:
# 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:
# From Odoo.sh shelltar -czf /tmp/filestore_backup.tar.gz /home/odoo/data/filestore/# Download from your local machinescp 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:
# On your new server: stop Odoosudo systemctl stop odoo# Drop the empty database and restore from backupsudo -u postgres dropdb odoo_productionsudo -u postgres pg_restore -d odoo_production --no-owner production_backup.dump# Extract filestoresudo 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 Odoosudo systemctl start odooStep 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
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.
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.
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.
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.
# Example: Import contacts via XML-RPCimport xmlrpc.clienturl = "https://your-odoo.example.com"db = "odoo_production"uid = 2 # admin user IDpassword = "your-api-key"models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")# Create a partnerpartner_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.
# On the source server: create a compressed dumppg_dump -Fc -Z 5 -f /tmp/odoo_dump.backup odoo_production# Transfer to destination serverrsync -avz --progress /tmp/odoo_dump.backup user@new-server:/tmp/# On the destination server: create database and restoresudo -u postgres createdb -O odoo odoo_productionsudo -u postgres pg_restore -d odoo_production --no-owner --role=odoo /tmp/odoo_dump.backup# Don't forget the filestorersync -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.
# Step 1: Install new PostgreSQL version alongside the old onesudo apt install postgresql-16# Step 2: Dump from old versionsudo -u postgres /usr/lib/postgresql/14/bin/pg_dump -Fc odoo_production > /tmp/odoo_pg14.dump# Step 3: Stop old PostgreSQL, start new onesudo systemctl stop postgresql@14-mainsudo systemctl start postgresql@16-main# Step 4: Create role and database on new versionsudo -u postgres createuser -s odoo 2>/dev/null || truesudo -u postgres createdb -O odoo odoo_production# Step 5: Restore into new versionsudo -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 Odoosudo systemctl restart odooCross-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:
# For large databases, compress and encrypt during transferpg_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 restoregpg --decrypt /tmp/odoo_encrypted.dump.gpg | pg_restore -d odoo_production --no-ownerCheck 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 if an OCA module has been ported to 18.0git ls-remote --heads https://github.com/OCA/account-financial-tools.git | grep 18.0# If the branch exists, clone itgit clone https://github.com/OCA/account-financial-tools.git --branch 18.0 --depth 1Testing Workflow: Staging → Test → Production
Never test module migrations on production. Use this workflow:
- Development: Update the module code on your local machine or dev server. Fix import errors, deprecated API calls, and template issues.
- Staging: Deploy the updated module to a staging environment with a copy of production data. Run
-u module_name --stop-after-initto verify the upgrade script runs cleanly. - 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.
- 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
During Migration
Post-Migration
9Frequently Asked Questions
Related Guides
Backup and Recovery Guide
Set up automated backups and disaster recovery for Odoo.
OCA Modules Guide
Find, install, and manage 1000+ free community addons.
Odoo Staging Environments
Set up staging environments for safe testing before production.
Migrate from Odoo.sh
Step-by-step guide to leaving Odoo.sh for self-hosted.
OEC.sh vs Odoo.sh
Detailed comparison of features, pricing, and flexibility.
Odoo Migration Complete Guide
Planning, execution, and post-migration checklist for any Odoo upgrade.
OEC.sh Pricing
Find the right plan for your Odoo deployment and migration.
Odoo 17 Migration
Migrate to Odoo 17 from older versions.
Odoo 17 Hosting
Deploy Odoo 17 on any cloud with OEC.sh.
Odoo 18 Migration
Upgrade to Odoo 18 LTS for long-term support.
Odoo 19 Migration
Upgrade to the latest Odoo 19 release.