Odoo Data Migration: How to Get It Right the First Time
Of every line in an ERP project plan, data migration is the one I see underestimated most often. After 100-plus Odoo implementations, I can tell you the software rarely sinks a go-live — the data does. It arrives late, it arrives dirty, and it gets loaded once, in a rush, with no clean way to undo it. Here is how I keep that from happening: what "migration" really means, what to move, and the mechanics that prevent a mess.
Two different problems people call migration
When a client says "migration," they usually mean one of two very different jobs, and conflating them is the first mistake.
The first is a fresh-system data import: moving off a legacy system — spreadsheets, an old accounting package, another ERP — into a brand-new Odoo database. Odoo imports into any of its business objects — contacts, products, bank statements, journal entries, orders and the rest — from either Excel (.xlsx) or CSV (.csv) files.
The second is a version upgrade: your data is already in Odoo, and you are moving the database from one major version to a newer one. That is not an import — it is a managed process Odoo runs on its own upgrade platform. Odoo draws a hard line here: the upgrade service does not cover migrating from another ERP into Odoo, or switching editions or hosting type. The tools and risks differ completely, so I'll take them in turn.
What to migrate and what to leave behind
Before touching a single import file, decide what actually needs to move. This is the conversation that saves the most money, and my default answer surprises people: move less than you think.
- Master data — yes. Customers, vendors, products, the chart of accounts. Odoo has a dedicated business object for each.
- Open items — yes. Unpaid invoices, open supplier bills, undelivered orders, current stock. You need these live on day one to keep trading.
- Opening balances — yes, but as balances, not history. Load your closing trial-balance position as opening journal entries so the books are correct from go-live.
- Full transaction history — usually no. Years of posted invoices and closed tickets are the biggest source of migration effort and the least-opened data afterward.
My honest opinion after a hundred projects: dragging a decade of closed transactions into a fresh database is rarely worth it. Keep the old system read-only as your archive for the odd old invoice. It is a judgement call, not a rule, but the default should be lean.
The import mechanics that save you
Map your columns deliberately. When you upload a file, Odoo heuristically works out each column's field type from the first ten lines — a column of pure numbers, for instance, is only offered integer-type fields. Any column it misses, you set by hand from a dropdown, and in developer mode an "Allow matching with subfields" option gives you finer control.
Always click Test first. The workflow is: upload the file, adjust the CSV formatting options if needed, map each column to an Odoo field, click Test to confirm the data is valid, and only then Import. Odoo's documentation is blunt that imports are permanent and cannot be undone; the created-on and last-modified filters only help you find what a bad import touched afterward.
Use External IDs. This separates a controlled migration from a duplicate-ridden mess. An External ID is a unique identifier for each row, and you can reuse the IDs from your old software. Their power is in re-runs: if your file includes an External ID (or Database ID) column, Odoo modifies the records already imported instead of creating new ones. That is what lets you import the same file several times without duplicates — and the first load is never perfect. The catch is consistency: if an External ID is altered or removed between runs, Odoo may add a duplicate instead of updating the original. So keep them stable and never delete the ID column.
Odoo even builds a round-trip for updates: tick "I want to update data (import-compatible export)" in the Export pop-up and it adds the External ID column automatically, so you can edit the file and re-import it as a controlled bulk update. And plan for scale: very large imports can time out, so work in smaller batches.
Version upgrades: the official path
Upgrading an existing Odoo database is a different discipline that Odoo runs as a managed service. The shape is always the same: request an upgraded test database on your target version, test it hard, then — and only then — request the production upgrade.
The test database is your safety net, and Odoo neutralises it so it cannot reach the real world: scheduled actions are disabled, outgoing mail servers are switched off, payment providers and delivery carriers drop to sandbox mode, and bank synchronisation is turned off.
The production run mirrors the test, with the purpose set to Production — and it is a one-way door. Once requested, the database is unavailable until the upgrade finishes, and once it completes you cannot revert. So I schedule it for a low-usage window and rehearse on a fresh test database first.
Two constraints catch people out. Versions: you can only upgrade to a currently supported release, each major version getting three years of standard support, with the last unsupported version usable as a target for six months past its end-of-life. Custom code: a database with custom modules cannot be upgraded until a version of those modules exists for the target release. Odoo's service covers standard apps and Studio customisations but excludes modules built in-house or by third parties — Odoo partners included — unless they sit under a maintenance-of-customisations contract. The upgrade is free on Odoo Enterprise; making your customisations compatible is the part you plan and resource.
The through-line: whether you are importing into a new system or upgrading an old one, the rule is the same — never do it once, never do it in production first, and always keep a way to check the result before anyone starts working.
The migration mistakes I keep seeing
The same failures recur, and every one is avoidable:
- Loading dirty master data as-is. Duplicated customers and half-finished products do not improve inside Odoo — they multiply. Clean before you load.
- Skipping External IDs. Without them, your second import run duplicates records instead of updating them — and the first run is never perfect.
- Migrating history nobody reads. Teams burn weeks moving years of closed transactions no one opens again. Archive the old system instead.
- No reconciliation sign-off. If finance has not confirmed that opening balances and open items tie back to the old system, you are not live — you are guessing.
- Big-bang with no test cycles. One import or upgrade, straight into production, no rehearsal. Imports cannot be undone and production upgrades cannot be reverted — the riskiest way to run the job.
How I run a migration
My sequence rarely changes:
- Scope the data — agree what moves and what stays in the archive.
- Clean at source — deduplicate and fix the data before it goes near Odoo.
- Build the templates — one per object, with an External ID on every record.
- Test-import into a test database, in batches, using the Test step every time.
- Reconcile and get written sign-off from finance on balances and open items.
- Cut over — final load into production during a quiet window, then verify counts and totals.
For a version upgrade the spine is identical: test database, rehearse, reconcile, then a scheduled production run. That discipline is what makes migration boring — exactly what you want on go-live day.
Odoo's import tools, upgrade process and version-support windows change over time, and the details here reflect Odoo's published documentation for version 19.0 as of July 2026. Always confirm the current behaviour in the Odoo import documentation and upgrade documentation before planning a project around them.
Frequently asked questions
Can I undo a data import in Odoo?
How do I import data into Odoo without creating duplicates?
How does an Odoo version upgrade work?
Will my custom modules survive an Odoo upgrade?
Related reading
More guides from my desk: what actually drives Odoo implementation cost in the UAE — where data migration is one of the biggest and most underestimated drivers; Odoo 19 new features — what actually matters — a first-hand look at the release you may be upgrading toward; and Odoo Community vs Enterprise — how to choose — the edition decision that determines whether your upgrades are free and managed.
Planning a migration or an upgrade?
I'm an Odoo Techno-Functional Consultant in Dubai and Head of Projects at Techbot Information Technology LLC, a UAE Odoo partner — 10+ years, 100+ implementations, certified across Odoo v13, v14, v15, v16, v18 and v19, and I presented the new features of Odoo 19 at Odoo Experience 2025 in Brussels. Tell me about your current system and I'll give you a scoped, honest view of what your migration or upgrade would actually involve — at no cost.
Get a free business evaluation