Blog post

Odoo 20: what actually changed, and who should upgrade

Odoo 20 raises the server baseline to Python 3.12 and PostgreSQL 16, keeps AI behind Enterprise credits, and drops record rules. What that means before you upgrade.

Isometric illustration of a modular ERP software dashboard glowing in cyan and orange on a dark background

Odoo 20 arrived in September 2026, and the release notes lead with agents, AI fields, and a model context protocol server. For a company that runs its own database, that is the least interesting part of the release. The parts that decide your next six months are a higher server baseline, an edition boundary for built-in Odoo AI, and a rewrite of how access rights scope records.

What follows is a reading of the official release notes, the 20.0 installation documentation, and the support lifecycle table, filtered for what changes on a self-hosted installation and what that costs the business depending on it.

The server baseline moved on two fronts

The Odoo 20 source-installation requirements set Python 3.12 or later and PostgreSQL 16 or later as minimums. These are runtime requirements, not a mandate to replace the whole operating system.

Stock Debian 12 and Ubuntu 22.04 packages are below both minimums. Refreshing the host or container may be the simplest operational route, but it is a recommendation, not an Odoo requirement; assess the available Python and PostgreSQL upgrade paths for your deployment.

  • Debian 12 ships Python 3.11 and PostgreSQL 15.
  • Ubuntu 22.04 ships Python 3.10 and PostgreSQL 14.

Neither stock package set clears both minimums. Depending on how the system is packaged, you may be able to upgrade components in place or choose a refreshed base image; a full OS migration and dump-and-restore are not the only technical options. If your deployment lives in Ansible roles, Dockerfiles, or hand-built servers, cost the infrastructure work before the Odoo upgrade begins.

For the conditional AI dependency, the installation documentation says pg-vector is required for Odoo AI features and is available on PostgreSQL 15 and later. PostgreSQL 16 therefore meets that version floor; enable the extension if you use those features.

If the new host also has to carry mail for Odoo, the delivery setup breaks more often than people expect during a move; Odoo email setup with SPF, DKIM, and DMARC covers the records that need to follow the IP address.

AI is Enterprise-only, metered, and partly external

The Odoo 20 release notes introduce agents configured with prompts, skills, and sources; AI fields; and a Model Context Protocol (MCP) server. The built-in AI documentation covers features such as transcription, image generation, and live-chat replies. Separately, the MCP server documentation explains how an external AI client can connect to Odoo and use database tools. For teams already running agent tooling elsewhere, that integration may be the more consequential change.

Three caveats decide whether any of it reaches your installation.

The first is edition. Asked directly on Odoo’s own forum why the AI module is missing from Community 19, the answer given there is unambiguous: “The AI features are only available with the Enterprise Edition of Odoo.” Nothing in the 20.0 release notes changes that boundary, and a Community 20 database should be expected to ship without the AI app.

The second is billing for built-in Odoo AI. Its official documentation says Odoo AI requests use In-App Purchase (IAP) credits. The same page says installing the AI app on the Standard pricing plan triggers an upsell to the Custom plan. This billing description applies to the built-in service; the documentation does not establish IAP credit pricing for external MCP clients.

The MCP documentation describes connecting an external agent using the user’s own local AI workflows. That is distinct from built-in Odoo AI: provider, model hosting, and any associated costs depend on the external client’s setup. The docs do not say that MCP use requires Odoo inference credits.

For a small business the practical reading is short. If the plan for moving to 20 was to get AI, the upgrade is not the purchase. Licensing and IAP credits apply to built-in Odoo AI; with an external MCP client, model/provider access and any associated costs depend on that client’s setup.

Access rights lost their record rules

Buried in the general section of the Odoo 20 release notes is the change with the longest tail for anyone maintaining custom modules: “Access rights have been simplified by removing record rules and adding a domain directly at the access right level to determine which records the access right applies to.”

Record rules were the standard way to express per-team, per-company, or per-record-type visibility in Odoo. They lived in ir.rule, usually as XML in a security file beside the ir.model.access entries. That object no longer carries the model. Scoping now rides on the access right itself as a domain, which is cleaner to reason about and less code to maintain, but it is a schema change your modules have to absorb.

Two consequences follow. Auditing gets easier, because record visibility is expressed in the same place as the permission that grants it. Porting is not free, because every ir.rule your custom code or a third-party module relies on has to be re-expressed as a domain. Multi-company and per-salesperson visibility is exactly where a quiet mistake turns into either a data leak or an empty list view, so inventory those rules before the test upgrade instead of after it.

Smaller changes with real operational weight

A few items from the Odoo 20 release notes deserve attention beyond the headline:

  • Tracking values are gone from mail threads. The tracking message is generated on the fly instead, and admins who still need the stored values can install a dedicated module. Custom reports that read those stored values stop working, while the built-in features that depended on them were reworked around the generated messages.
  • Font Awesome has been replaced by Material Symbols. Custom views, themes, and components that hardcode fa-* classes will render wrong rather than fail loudly, which makes the regression easy to miss in a quick test pass.
  • Offline mode now covers create, edit, archive, unarchive, and delete, plus re-running searches made earlier. Field teams and warehouse staff gain the most, and the test plan should cover conflicting edits from two devices.
  • The decimal separator is independent of the localization configured in a user profile, which removes a frequent complaint in mixed-locale teams.
  • Orders and invoices carry a tax included/excluded toggle with a per-tax override, eCommerce gains stock-driven automatic publish and unpublish, and returns can run through the customer portal.

None of these justifies a migration on its own. Together they change the test matrix, which is a different thing from change itself.

The integration side of Odoo has not changed shape in this release, and the older advice still holds: give each system one job and one source of truth, as in connecting Odoo, HubSpot, and Airtable without data silos.

Who should move, and when

The Odoo support lifecycle table makes the timing question concrete. Odoo 20 sits in standard support until September 2029 (planned). Odoo 19 standard support is planned to end in September 2028; Odoo 18 in September 2027, while Odoo 17 standard support ended in September 2026. These dates are from the official support lifecycle table.

That splits installations into three groups.

On 17 or older, standard support has ended. Security updates are only provided during standard support. Both phases include helpdesk support and bug fixes. During extended support, fixes are provided only where technically feasible. Extended support does not restore security updates; consult the support lifecycle terms for eligibility. This group is not really choosing whether to upgrade; it is choosing how long to run unsupported software. The complication is the size of the jump, since every version in between adds porting work, and skipping versions usually costs more in module repairs than it saves in elapsed time.

On 19, there is no urgency, and the case for moving is specific: offline mode for field work, the tax toggle, stock-driven storefront publishing, or an MCP integration that fits your workflow. On a working system with healthy custom modules, staying is a defensible engineering decision; Odoo 19 standard support is planned to end in September 2028.

On 18, the window is narrower than it looks. Standard support ends in September 2027, so the realistic choice is one larger upgrade later against a smaller one now, while the infrastructure work is already on the table.

How the migration actually runs

For Enterprise and paying on-premise customers, the upgrade platform is the documented route. You request an upgraded copy of the database for testing, through the upgrade website or the CLI script, and the machine making the request needs database access plus outbound HTTPS and the port range 32768–60999 open to the upgrade service. The platform preserves the edition; it does not switch editions, downgrade, or move hosting.

The upgrade documentation recommends requesting an upgraded test database while porting custom modules in parallel. Use migration scripts under $module/migrations/<version>/ and upgrade utilities for renames. Odoo 20 also ships odoo-bin upgrade_code --from 19.0 --to 20.0, which rewrites deprecated calls in your source. Compatible modules are needed for usable final testing and go-live, not before you request the test database. The code tool is best-effort, not a guaranteed port, and it cannot make the access-rights decisions for you.

Community installations have no access to that platform. The open-source route is OpenUpgrade, the OCA-maintained set of upgrade scripts run through the openupgrade_framework module. Confirming that the 20.0 scripts are published and cover the modules you actually run is a verification step, not an assumption to build a delivery date on.

A pre-upgrade checklist that earns its keep

  • List every custom and third-party module, and mark which ones define ir.rule records, hardcode fa-* icon classes, or report on stored tracking values.
  • Check the host against both floors in one pass with python3 --version and psql --version, then confirm the distribution can actually provide those versions.
  • Rehearse a full backup and restore before the maintenance window, and time it. If your chosen PostgreSQL upgrade path uses a dump and restore, test that exact procedure against the target instance in advance.
  • Run the business flows on the upgraded test copy: a quote, an invoice with tax included, a stock-out with a published storefront product, and one case per visibility rule your teams depend on.
  • Decide the AI question separately from the version question, with edition requirements and IAP credit costs for built-in Odoo AI in front of you rather than a release video; assess an external MCP client’s model/provider costs separately.
  • Keep a restore point you have tested. A pg_dump that has never been restored is a hope, not a backup.

Odoo 20 is a normal release with an above-average infrastructure bill attached. The version number is not the decision. The decision is which of three pressures applies to you: an unsupported 17 install, a server that has to be rebuilt for Python 3.12 and PostgreSQL 16 anyway, or a custom module that the access-rights rewrite will break. Everything else in the release can wait for a quiet month.

Related areas

These What I Do pages are matched from the subject matter of this article, creating a cleaner path from educational content to implementation work.

Continue reading

Based on shared categories first, then the strongest overlap in tags.