Skip to Content

External IDs: the anti-duplicate weapon in Odoo data recovery

Importing for the first time is easy. Being able to update cleanly ten times without ambiguity is where the External ID changes everything.
December 24, 2025 by
External IDs: the anti-duplicate weapon in Odoo data recovery
AUGURIA, Cyrille de LAMBERT

Auguria News

Data migration is a classic: you load a first version 'to get started', then come the adjustments... and the adjustments of the adjustments. In an Odoo project,imports are almost always iterative: mapping corrections, enrichment, cleaning, structural changes, new records that appeared during the project, etc.

And to prevent each new import from turning into a duplicate factory (or a 'feeling-based matching' session), Odoo offers a tool that is as simple as it is powerful:External IDs (external identifiers, sometimes calledXML IDs). Odoo

Why data migration is (almost) never a 'one shot'

Even with serious preparation, there always comes a moment when you say:

  • 'We forgot a column'

  • 'In the end, we are changing the structure of the categories'

  • 'We want to enrich the product sheets'

  • 'We need to correct addresses'

  • 'The old system continued to live, we need to reintegrate the new items'

The real question is therefore not 'how to import once?', but:

How to re-import to update — without duplicating, without ambiguity, and without makeshift solutions?

Three identifiers not to be confused

1) The internal Odoo ID (Database ID)

C’est l’identifiant interne d’un enregistrement dans la base. Dans PostgreSQL, il s’agit bien, dans la plupart des modèles persistants, d’une colonne id qui sert de clé primaire (créée/maintenue automatiquement) — ce n’est pas un “champ métier” et il n’est pas conçu pour être partagé entre bases ou environnements. Odoo

Dans l’interface d’import Odoo, tu peux d’ailleurs voir la notion de “Database ID” (ID base de données) comme colonne possible. Odoo

What to remember:

  • technically useful,

  • unstable from one database to another(test → prod, or reimport 'blank'),

  • not suitable as a 'business' exchange key.

2) The reference (or a business field)

Very useful on a daily basis, but:

  • it can change (new coding),

  • be entered incorrectly,

  • or not be unique.

It often helps tofind... but not always toupdate unambiguously.

3) The External ID (stable matching key)

It is a technical key managed by Odoo (via ir.model.data) that associatesa recordwitha stable external identifier(often constructed as module.name).

And especially: when importing,if your file contains a column 'External ID', Odoo updates the already imported records instead of recreating them, which allows you to replay the same file after corrections.

"You can already find the object with the reference." Yes... but that's not the real issue.

One might say:"You can already find the object with the reference."

That's true... when the reference is clean, unique, stable, and everyone respects it religiously (spoiler: rarely).

The issue of data recovery is rather to:

  • update the correct record

  • automaticallyand

  • et replayable

The very common case: multiple clients with the same name

In real databases, we often see:

  • multiple "Central Store"

  • multiple "Paris Boutique"

  • multiple "Lyon Agency"

Typically: a chain of stores, or secondary establishments.

Without an External ID, an update based on the name (or a pseudo-reference) becomes:

  • either a fragile match ("name + postal code + city..."),

  • or a source of duplicates,

  • or worse: an update of the wrong record.

With an External ID based on the unique identifier of the old system:

  • you know exactly which one you are updating

  • et tu peux réimporter autant de fois que nécessaire sans ambiguïté.

The concrete advantages of External IDs in data recovery

1) Replayable imports: creation on the first pass, updates on subsequent ones

Odoo handles this very clearly:if you import with "External ID", the already imported records are modified, not recreated.

This is the basis for a smooth recovery: you can correct your file and re-import it.

2) Incremental recovery: you progress in waves (like a serious project)

  • V1: minimal base (clients/products)

  • V2: enrichment (categories, tags, conditions)

  • V3: corrections and normalization

  • V4: last-minute additions

And all thiswithout turning your database into a graveyard of duplicates.

3) Relationships between objects that are much more robust

Odoo explicitly recommends using the unique identifier from the source application to rebuild links via columns of the type XXX/ID (relation to the External ID).

This is particularly valuable for:

  • companies ↔ contacts ↔ addresses

  • products ↔ categories ↔ variants

  • products ↔ suppliers

  • price lists ↔ pricing rules

4) An “updatable” process (the right wording)

Rather than “reversible,” the idea is:

a reproducible, controllable, and replayable process for successive updates.

This is exactly what the External ID column allows during import.Odoo

Recommended methodology (simple and effective)

Step 1 — Require a stable unique identifier on the client side

Ask the client for their unique identifier(old system) for:

  • clients / suppliers

  • products

  • categories

  • etc.

Step 2 — Define a naming convention

Examples:

  • legacy_partner_12345

  • legacy_product_98765

  • legacy_category_42

Goal: avoid collisions, remain readable.

Step 3 — (Recommended) Also keep the historical identifier in a “business” field

In addition to the External ID (technical), keeping a field like “Old system identifier” helps:

  • the accounting,

  • the support,

  • and understanding from the users' side.

Step 4 — Initial import, then update imports

You import for the first time, then you replay:

  • Odoo met à jour via External ID.

After the migration: “the External IDs return to their normal life”

Important point: yes, it’s mainly during the migration that the External ID is a star, because it’s the time for reimports and adjustments.This is actually one of the key documented uses:reimporting the same file to update without creating duplicates, and rebuilding relationships via XXX/ID.

After go-live:

  • you don’t have to talk about it every morning (we already have enough topics),

  • the External IDs you set during the migration remain a very useful technical foundation if you need to replay imports / correct / interface,but

  • for the pour les new recordscreated over time (by users, automations, etc.), there is generally no “readable” External IDcreated “business” by default.

And this is where many discover it during export:

if no proper External ID exists, Odoo can generate a generic identifier like __export__.sale_order_1884 (or equivalent), useful for the machine… much less so for humans.

Conclusion

Importing a database into Odoo is good.

Being able to update it properly ten times, without duplicates and without ambiguity, it's better.

External IDs are not "a technical gadget": they arethe railsthat transform a data takeover into a controlled process. And once the migration is complete, they remain discreetly in their place — like the best traditions: those that avoid unpleasant surprises.

If you want, I can also offer you a "case study" version (chain of stores + multi-reference products) with an import file structure and the exact columns to expect.

in Blog
External IDs: the anti-duplicate weapon in Odoo data recovery
AUGURIA, Cyrille de LAMBERT December 24, 2025
Share this post
Tags
Our blogs