← Back to blog
·10 min read·tryexcept

Upgrading Custom Odoo Modules to Odoo 20: What Breaks and How to Plan It

OdooOdoo 20UpgradeOdoo DevelopmentCustom ModulesAPI

Odoo's upgrade service handles the standard part of your database: schema changes, data migration and Odoo's own modules. It does not upgrade your custom code. Odoo's documentation is clear that a database with custom modules cannot be upgraded until a version of those modules exists for the target version. This guide covers the Odoo 20 changes most likely to affect custom modules and integrations, based on the release notes and documentation, plus what we see go wrong in real upgrades.

Platform requirements

  • Python 3.12 to 3.14 (Odoo 19 accepted 3.10 and up).
  • PostgreSQL 16 or later (Odoo 19 accepted 13 and up).
  • For self-hosted systems this can mean an operating system upgrade and a PostgreSQL major upgrade before Odoo itself. Check your Python dependencies as well: older pinned libraries may not install on Python 3.12.

Security: record rules are gone

This is the biggest change for custom modules. Odoo 20 simplifies access rights by removing record rules and adding a domain directly on the access right, which decides which records that access right applies to. Any module that ships its own record rules, such as multi-company rules, "own documents only" rules for salespeople or portal rules, needs its security definitions redesigned, not just renamed. Plan time to test each user role, because security mistakes do not raise errors. They quietly show people too much or too little.

Chatter: tracking values are gone

Tracking values have been removed, and tracking messages in the chatter are now generated on the fly. Odoo has updated its own features that used them, such as burndown charts and stage duration, and offers a dedicated module for anyone who still needs tracking values. If your code reads tracking values directly, for example custom reports on stage history, audit exports or integrations that watch for field changes, it needs rewriting or that module.

Interface: Material Symbols replace Font Awesome

Font Awesome icons have been replaced by Material Symbols across the interface. Custom form views, kanban cards, QWeb reports, website templates and Owl components that use fa- icon classes need checking. Missing icons rarely break anything, but they make a custom screen look broken to users on day one.

Functional changes that affect custom code

  • Accounting structure: account groups are replaced by parent accounts, and account codes are optional. Reports, exports and integrations that key on account codes or groups need reviewing.
  • Assets: asset models are replaced by depreciation models.
  • Payment status: "In Process" is renamed "Paid" and "Paid" is renamed "Reconciled". Anything that reports on or reacts to payment status needs re-testing.
  • Expenses: approved expenses now create draft bills, and the Employee Expenses menu is removed.
  • Payroll: work entries are removed and merged with time off types, and the Planning to Payroll integration is gone. Custom salary rules that read work entries need rework.
  • Field Service: the app is discontinued and merged into Planning. Any module that extends Field Service needs to be re-targeted.
  • Manufacturing: flexible consumption is always on. Customisations that relied on strict consumption need a fresh look.

Integrations: the XML-RPC and JSON-RPC deadline

Odoo's external API documentation now states that the XML-RPC and JSON-RPC APIs at /xmlrpc, /xmlrpc/2 and /jsonrpc are deprecated. The database service was removed in Odoo 20. The common and object services, which most integrations use to log in and read or write records, are scheduled for removal in Odoo 22 (fall 2028) and Online 21.1.

  • The replacement is the JSON-2 API, available since Odoo 19: you POST JSON to /json/2/<model>/<method> with a bearer API key.
  • It needs the Custom plan. Odoo's documentation says external API access is not available on One App Free or Standard.
  • Plan the switch with your upgrade. If you are touching integrations for Odoo 20 anyway, move them to JSON-2 now rather than doing the work twice before Odoo 22.

What breaks that is not in your modules

In real upgrades, the failures that hurt most are not in the Git repository. They live in the database and only fail when someone triggers them, often days after go-live:

  • Automated actions and server actions with Python code that references renamed fields. Two examples from upgrades to Odoo 19: groups_id on users became group_ids, and product_uom on sales order lines became product_uom_id. Code written years ago against the old names fails the first time the action runs.
  • Studio customisations: fields, views and reports built in Studio that depend on fields or views Odoo has changed.
  • Website pages edited in the builder: edited pages are stored as copies of Odoo's templates. After an upgrade an old copy can override the new template and leave a page blank or broken. Customer portal pages are a common example.
  • Email templates and reports with QWeb expressions that reference old fields.
💡

Before any upgrade, export a list of every automated action, server action, Studio field, edited view and email template, and search their code for fields you know have changed. It takes an hour and saves days of post-go-live firefighting.

Coming from Odoo 16, 17 or 18

If you jump several versions at once, your modules take on every change in between, not just Odoo 20's. Two that affect almost every module: Odoo 17 removed the attrs attribute in views in favour of direct invisible, readonly and required expressions, and Odoo 18 renamed tree views to list. Frontend code written for older versions of the Owl framework usually needs updating too. None of this is hard, but it adds up, so audit before you quote.

A practical upgrade plan

  • 1. Audit: list every custom and third-party module, its size and which areas it touches (security, accounting, payroll, Field Service, chatter tracking). Check every third-party module has a version 20 release.
  • 2. Request a test upgrade from Odoo straight away. Odoo recommends porting your modules in parallel rather than waiting.
  • 3. Port and test the modules, starting with security definitions. Write automated tests for the business rules you care about if you do not have them.
  • 4. Move integrations to JSON-2 while you are there.
  • 5. Run the database customisations check above on the upgraded test copy.
  • 6. User acceptance testing on staging with real workflows and each user role.
  • 7. Rehearse the final upgrade with fresh production data, then go live over a weekend with a week of close support.

For a sense of scale: in our Odoo 16 to 19 upgrade case study, four custom modules were ported in about a week, with one needing a partial rewrite. The whole project took six weeks. If you want a team to do it with you, see hire an Odoo developer in Australia.

Sources

Need your custom modules ported to Odoo 20?

We are a developer-led Odoo partner. We audit your modules, port them, write the tests and run the upgrade with you, at a fixed price. Send us your repository and we will scope it.

Get in touch →