Khichdi InfoTech
Skip to content

Odoo Migration · advanced · 13 min read

Migrating Custom Modules

How to port custom Odoo modules during migration: compatibility triage, manifest updates, migration hooks, view and API fixes, and sequencing module -u with database upgrades.

Last reviewed 2026-07-30 · Estimated effort: 6+ weeks for multi-team change

Table of contents

Custom module migration is iterative porting work revealed by staging dry runs: update manifests and dependencies, fix deprecated APIs and views, add migration hooks for data shape changes, and re-run -u until critical workflows pass UAT.

Triage before porting — retire modules superseded by standard Odoo, replace thin wrappers with configuration, and escalate brittle Studio-only logic. Not every customization deserves a porting budget.

Engineering quality — inheritance patterns, upgrade-friendly code, tests — belongs in the Development pillar. This article focuses on migration programme mechanics: backlog, sequencing, and sign-off gates for module porting.

Dry runs fail on custom modules long before core Odoo surprises anyone. A structured porting backlog turns traceback noise into prioritized tickets with owners and acceptance tests.

For deep ORM, view, and security engineering guidance, use the Development guide — especially upgrade-friendly coding practices. Here we cover how module porting fits the migration lifecycle.

Classify each custom and third-party module: must-port for legal or operational reasons, nice-to-have, replace with standard feature, or retire. Missing source code or unknown authorship forces a hard decision — re-build, replace, or drop.

Score complexity from dependency depth, web client assets, report engines, REST controllers, and cross-module coupling. High-coupling modules port early because they unblock downstream tests.

  • Manifest version and installable flag on target Odoo
  • Last known working version and Git commit
  • Business workflow mapped to module technical name
  • Third-party license and maintainer contact

Typical sequence: bump manifest version and depends, install on dev against upgraded database copy, fix import and API breakages, update XML views and security CSV, add migration hooks for renamed fields or models, run module tests, promote to staging dry run.

Keep changes in feature branches per module or epic. Merge only when staging -u succeeds without traceback for that module set and linked UAT scenarios pass.

Use pre/post migration hooks in module code for field renames, default value backfills, and cleanup of obsolete models — co-located with the module so upgrades remain repeatable. Avoid scattered one-off fixes unless documented in the database migration runbook.

When multiple modules touch the same model, coordinate hook order via dependencies. Conflicting hooks discovered in dry run 2 should be resolved before UAT sign-off.

Module -u runs against an already upgraded database schema from core migration. Programme order: core DB upgrade path on staging copy, then layered module updates in dependency order, then full integration smoke tests.

Freeze new module installs in production during stabilization. Hotfix modules follow the same branch and staging promotion path — no direct production edits during hypercare except via agreed emergency process.

  • Port high-dependency modules first; retire before rewriting when standard Odoo covers the workflow.
  • Require Git history and manifests for every must-port module before estimating effort.
  • Pair each porting ticket with a UAT scenario — not only a green server log.
  • Follow Development guide patterns for upgrade-friendly inheritance and tests.
  • Track third-party modules without maintainers as explicit programme risks.

  • !Porting every historical customization without triage.
  • !Editing production modules without staging -u proof.
  • !Fixing views only in the UI while server-side constraints still fail.
  • !Ignoring JavaScript asset and OWL changes in web client modules.
  • !Skipping module tests because manual click-through once worked.

Custom module migration succeeds with triage, dependency-aware porting, versioned hooks, and staging proof tied to UAT — not heroic cutover debugging.

Combine this with structured testing and compatibility review before locking cutover.

Triage → branch → fix → -u → UAT gate per module.
1

Freeze scope

Known module set.

2

Dry-run

Full upgrade on staging.

3

Fix gaps

Module and data repairs.

4

Rehearse cutover

Timing and rollback.

Core DB upgrade then layered module -u dependencies.
  • Client / Channel

    Users & devices

  • Odoo Application

    Business logic

  • PostgreSQL

    System of record

  • Workers / Cron

    Async work

  • clientapp(HTTP)
  • appdb(ORM)
  • appjobs(queue)

Frequently asked questions

Do all modules need rewriting on every major version?

No. Well-structured modules with limited deprecated API use may need modest manifest and view updates. Heavy web client customization or old API patterns cost more — dry runs reveal which.

Where do migration hooks belong?

In the owning module when the fix is module-specific and must repeat on future upgrades. One-time estate-wide cleanup may live in documented database scripts — see database migration best practices.

Should we read the Development guide too?

Yes. Migration tells you when and how porting fits the programme; Development tells you how to engineer modules that survive the next upgrade.

Large custom module estate to port?

We triage, port, and test addons with dry-run discipline — using upgrade-minded patterns from our development practice.

Business technology and software delivery