Why the audit matters
Upgrading Odoo isn’t just a matter of translating code from an old API to a new one. If you treat a migration strictly as a coding task, you’re going to have a rough time. The real make-or-break phase of any upgrade happens before you touch a single line of code: the pre-migration audit.
A good audit is your project’s blueprint. It keeps scope in check, helps knock out technical debt, and catches all those hidden landmines that usually blow up your staging timeline.
Here’s what an effective pre-migration audit needs to cover.
1. Don’t Migrate What You Don’t Use
Not everything in your current system deserves a ticket to the new version. Over the years, every Odoo instance collects its fair share of unused modules, dead features, and forgotten models. Porting dead code just burns budget and adds maintenance weight you don’t need.
How to isolate what matters
- Analyze Record Counts
- Look for custom models with a very small number of records (or zero).
- Use caution here to omit master data models, which naturally have few records but are absolutely critical to the system.
- Discuss With Users
- Data alone does not tell the whole story. Engage with key users and stakeholders to confirm whether a feature is genuinely obsolete or just used infrequently.
- Always ask them to confirm before deciding to drop a module.
Pruning your codebase upfront means you only spend time migrating code that actually brings value to the business.
2. Prioritize Refactoring Opportunities
A migration is a rare chance to fix architectural mistakes—assuming time and budget allow for it. Figure out which painful areas are worth rebuilding rather than just porting blindly.
Where to focus
-
Drop outdated libraries and protocols: Move away from ancient, unsupported Python packages or legacy integration methods. For example, if an old module still uses raw FTP, this is the perfect time to upgrade it to SFTP.
-
Check the OCA and standard features: The Odoo ecosystem moves fast. A custom feature you built from scratch three years ago might be a standard feature or a great OCA module today. It’s always worth checking around. For instance, you might be able to leverage stock_inventory, which was dropped from native Odoo but is fully maintained by the OCA.
Also, keep an eye out for interesting work-in-progress pull requests. Something like OCA/account-payment PR #923 might solve your exact problem right out of the box, saving you from writing custom code.
-
Write some tests: Use the migration as an excuse to add automated tests to your refactored code. It pays off immensely during the upgrade and saves you headaches down the road.
3. Find the Hidden Database Objects
Standard migration tools usually focus on Python files and XML manifests. The problem is, they completely miss everything that lives directly inside the PostgreSQL database. You need to catch these early.
What hides in the database
-
Raw SQL Triggers: Custom trigger functions written in PL/pgSQL that quietly run business logic completely bypassed by the Odoo ORM.
-
Manual Database Objects: Database views, materialized views, or custom constraints that an admin created directly in the DB ages ago.
-
UI-Created Automations: Users often go heavy on base automation, creating automated or server actions manually right from the UI. Because these are just database records lacking an XML ID, your standard code audit won’t see them at all.
-
Hardcoded Database IDs: It’s common to find manually created server actions or security rules laced with Python code or domain expressions relying on hardcoded IDs (like
record.country_id.id == 227).This is a massive issue because it makes fresh-database testing impossible. If you spin up a clean database to test your upgrade, those records will get entirely different IDs, totally breaking your logic. You are forced to rely solely on migrated production dumps for testing, which makes feedback loops painfully slow.
The fix? Audit these ID-dependent manual records, export them into proper XML data files (maybe prefix them with
manual_), and swap out the raw integers for stable external IDs.
If your audit misses these database-level tweaks, they’re going to stay hidden until they cause massive estimate blowouts and nightmare debugging sessions deep into your staging phase.
Key Takeaways
- It’s not just modules. Unused features, dead code, and forgotten models all add cost. Know what you’re actually migrating before you start.
- Use the migration to clean house. Old libraries, unmaintained custom code, and missing tests all have better options available today.
- The database holds secrets your code doesn’t. Triggers, manual views, UI-created automations — none of them show up in a codebase audit.
- Hardcoded IDs make testing a nightmare. You won’t be able to spin up a clean database to validate the upgrade. Plan your testing around that.
- Skip the audit, pay for it at staging. Every surprise that surfaces mid-migration is something the audit should have caught.