01 · ERP migration · In progress
Migrating a customised ERP from Odoo 13 to Odoo 19 Community
The company group runs accounting, inventory, HR, payroll, transport and maintenance on a heavily customised Odoo 13. I'm moving it to Odoo 19 Community. The audit is finished. Modules are now being ported and tested on a separate test server, and Odoo 13 is still the production system.
The problem
Odoo 13 has been out of Odoo's support window for years, and the group's business processes live inside it: accounting, stock, HR, payroll, transport, maintenance and a public jobs feed.
Odoo stores a lot of logic in custom modules, and many APIs those modules use no longer exist in Odoo 19. A plain database upgrade isn't possible. Each custom module has to be audited, ported and tested before any real data moves.
What I'm responsible for
- Audited the module tree and mapped which third-party modules the custom code actually depends on.
- Wrote the migration report that records every Odoo 13 → 19 incompatibility found.
- Porting the custom modules myself (Python models, XML views, security rules, reports) against the real Odoo 19 source.
- Built and maintain the separate Ubuntu test server and PostgreSQL test database server.
- Reviewed the licensing of every module in the dependency chain before choosing the Community edition as the target.
Architecture
The migration happens entirely beside production. Odoo 13 keeps running, and nothing is installed on it.
- Production (unchanged)
- Odoo 13 Community
- Production PostgreSQL database
- Filestore
- Code
- Custom modules in Git / GitLab
- Ported module by module
- Installed into throw-away Odoo 19 databases first
- Test application server
- Ubuntu 24.04
- Odoo 19 Community
- nginx reverse proxy · TLS · UFW
- Test database server
- PostgreSQL 16
- Copied test databases only
- Never connected to production
Engineering decisions
Target Odoo 19 Community, not Enterprise
The licensing review found six modules in the dependency chain that came from Odoo Enterprise source: accounting reports, assets, budgets, Gantt and grid views. Enterprise code can't be carried into a Community deployment, so those modules have to be replaced with Community/OCA alternatives or rewritten.
Migrate only what is actually used
The audit covered 375 module manifests. I traced the real dependency chain of the custom modules and found 46 third-party modules (about 225,000 lines of Python, XML and JavaScript). Everything outside that chain stays behind, which keeps the scope realistic.
Test databases only
Every module bundle is installed onto copied test databases on a separate PostgreSQL server. Production is never touched until data validation and a rollback plan are in place.
Drop legacy JavaScript instead of shimming it
Odoo 13 widgets use the odoo.define / Widget API that was removed in Odoo 17. I took them out of the asset bundles so views fall back to standard widgets. Anything users still need gets rewritten in OWL.
Technical challenges
Enterprise code blocking Community modules
Through the assets module, Enterprise code was a dependency of transport, technic, stock, timetable and salary. Unpicking that dependency comes before those modules can be ported.
HR contracts became versions
Odoo 19 merges hr.contract into hr.version. Every HR, timetable and payroll module that read contracts, including raw SQL reports, has to be re-pointed. Payroll is flagged for line-by-line comparison against Odoo 13.
Failures that only happened on the server
Some bugs only appeared on the test server, because modules installed there in a different order than on my machine. One of them blanked the whole web client. I traced and fixed each one and recorded it in the deployment log.
Removed stock models and view API changes
Several stock models used by the custom inventory code no longer exist, and view inheritance changed between versions. Each module is installed into a fresh Odoo 19 database and its main flows are tested at runtime, not just loaded.
Current status
Done
- Module audit and dependency mapping
- Written migration report
- Licensing review of the dependency chain
In progress
- Porting and runtime-testing custom modules
- Ubuntu 24.04 test server and PostgreSQL 16 test databases
- Replacing Enterprise-only dependencies
Planned
- Run a full payroll month on migrated data and compare every line with Odoo 13
- Configure stock valuation and reconcile a month of inventory
- Key-user acceptance testing
- Cutover with full PostgreSQL + filestore backup and a documented rollback path
Outcomes so far
- module manifests audited
- 375
- third-party modules in the real dependency chain
- 46
- lines of Python, XML and JS in that chain
- ~225k
- Enterprise-only modules to replace
- 6
- custom modules in scope
- 15
- A written migration report and dependency map. The scope went from "everything installed" to a defined set of modules.
- An Odoo 19 Community test environment running with migrated modules installed (screenshot below).
- Install-order bugs found and fixed on the test server before they could reach production.
Production cutover hasn't happened. I'm not claiming business or performance results until the migration is live and verified.
Screenshots

A new home screen isn't proof the migration works. The real evidence is the module installs and runtime tests on the test databases.