Odoo Migration · intermediate · 11 min read
Database Migration Best Practices
Practical PostgreSQL and Odoo database migration practice: backups, anonymized copies, migration scripts, performance tuning, and validating data after dry-run upgrades.
Last reviewed 2026-07-30 · Estimated effort: 2–6 weeks typical implementation slice
Table of contents
Database migration is the foundation of every Odoo version move: a restorable backup, a production-like staging copy, execution of Odoo core migration scripts, custom pre/post SQL or ORM hooks where justified, and validation that financial and operational data still reconcile.
Dry runs exist to measure runtime and surface data anomalies — not to prove login works once. Track script duration, table bloat, attachment volume, and long-running cron side effects across repeated runs.
Keep destructive fixes in versioned migration scripts tied to modules or documented runbooks — not ad-hoc production SQL during cutover unless pre-tested on identical copies.
Module porting gets attention; database work often decides whether cutover finishes on time. Core Odoo handles much of the schema evolution, but custom fields, orphaned data, and third-party tables still need explicit handling.
This article covers database methodology. Custom module engineering belongs in the module migration and Development pillars — cross-link rather than duplicating ORM patterns here.
Before any dry run, verify backups: PostgreSQL base backup or pg_dump, filestore if attachments matter, and configuration secrets stored separately. Restore to an isolated server at least once per programme — a backup that never restored is a hope.
For cutover, take a final backup immediately before maintenance begins and confirm restore steps align with rollback planning. Document backup location, retention, and who can authorize restore.
- ▸Test restore to non-production hardware or volume
- ▸Include filestore when documents and images are business-critical
- ▸Record backup checksum or size for cutover night verification
Refresh staging from production on a schedule. Anonymize PII where required but preserve row counts, attachment sizes, and fiscal history needed for realistic script runtime. Subset copies are acceptable for early dev cycles; full copies should precede final UAT.
Align PostgreSQL version, extensions, and locale settings with production targets. Surprises from mismatched extensions belong in dry run 1, not cutover.
Odoo's upgrade service or open-source migration tooling applies versioned core scripts during -u on the target codebase. Custom work typically adds module migration hooks (pre/post init), SQL for legacy cleanup, and data transforms for fields that changed shape between versions.
Script every repeatable fix. One-off manual SQL in psql during cutover should already have succeeded on the last dry-run snapshot. Prefer ORM migration in module hooks when business rules must run — raw SQL when volume or simplicity demands it.
Large mail_message, stock_move, and account_move tables dominate upgrade time. Monitor autovacuum, index health, and disk IO during dry runs. Batch cleanup scripts may run pre-upgrade to remove obsolete logs if policy allows.
Log start/end timestamps per major step in the runbook. Use dry run 2 and 3 to refine estimates; add buffer for cutover — networks, human verification, and integration restarts add time beyond raw script duration.
Automate reconciliation where possible: trial balance tie-out, open PO/SO counts, stock valuation snapshot comparison, partner and product counts. Manual spot checks complement — they do not replace — aggregate validation.
Scan ir_module_module for failed states, review upgrade logs for tracebacks, and confirm cron jobs are active but paused if needed until smoke tests pass.
- ✓Restore-test backups before the first dry run, not the night before cutover.
- ✓Version all custom migration scripts in Git with module or runbook references.
- ✓Measure full upgrade duration on production-sized copies before publishing downtime windows.
- ✓Validate financial and stock aggregates automatically after each dry run.
- ✓Document PostgreSQL and Odoo versions used during successful dry runs.
- !Running upgrades only on empty databases with unrealistic runtime.
- !Manual production SQL fixes never tested on a full copy.
- !Omitting filestore from backup and restore planning.
- !Assuming core scripts fix third-party module tables without errors.
- !Skipping log review because the UI loads after upgrade.
Reliable database migration rests on tested backups, realistic staging copies, versioned scripts, measured dry runs, and automated reconciliation — not optimism.
Pair database practice with structured module porting so schema and code upgrades stay aligned.
Freeze scope
Known module set.
Dry-run
Full upgrade on staging.
Fix gaps
Module and data repairs.
Rehearse cutover
Timing and rollback.
- Owners named
- UAT scripts signed
- Rollback documented
- Hypercare roster ready
Frequently asked questions
Should we use Odoo's upgrade service or self-hosted dry runs?
Both are valid. Upgrade service simplifies core script application for many estates; self-hosted dry runs give tighter control for custom modules and repeated iteration. Often programmes use both at different stages.
When is raw SQL acceptable during migration?
When volume, simplicity, or one-time cleanup demands it — but only after testing on identical copies and documenting in versioned runbooks. Prefer module hooks when business logic must execute.
How do we handle attachment bloat?
Measure filestore size early. Archive or deduplicate per policy before final dry runs if runtime or disk constraints threaten the maintenance window — plan with legal and operations first.
Related articles
Planning an Odoo Migration Project
How to plan an Odoo migration: inventory workshops, environments, milestones, RACI, acceptance criteria, and cutover sequencing for business owners and technical leads.
View →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.
View →Testing an Odoo Migration
Structured UAT and technical testing for Odoo migrations: scenario scripts, regression scope, integration smoke tests, performance checks, and sign-off gates before cutover.
View →Rollback Planning
How to plan Odoo migration rollback: backup strategy, rollback triggers, restore runbooks, communication templates, and decision authority during cutover.
View →Related services
Odoo Migration & Delivery
Planned upgrades, module migration, and cutover delivery for production Odoo systems.
View →Odoo Rescue
Audit-first recovery when a migration or upgrade is stuck or broken.
View →Dedicated Odoo Developer
Reserved capacity for module porting, test fixes, and migration backlog.
View →Worried about database runtime or data integrity on upgrade night?
We run production-sized dry runs with reconciliation checks and documented scripts — so downtime estimates reflect reality.
