If you’re running Odoo 15 or older, you’ve probably already seen the number: Odoo’s 2026 contract terms apply a 25% surcharge to v16 and below. It reads like the whole story — pay the tax, or migrate and stop paying it. But that surcharge is a symptom, not the disease. It’s the one cost Odoo can put a line item on. The costs that actually hurt you don’t show up on an invoice. They show up as a support ticket that goes nowhere, a security patch that never arrives, or a migration quote that’s twice what it would have been two years earlier.
Here’s what actually compounds, in roughly the order it bites.
1. The surcharge is real, but it’s the visible tip
Twenty-five percent on your Odoo Enterprise licence is not nothing — on a mid-size contract that’s a genuine five- or six-figure annual number in rupees. But it’s a flat, predictable tax. You can budget for it. The problem is that budgeting for the surcharge tends to make it feel like the whole problem is priced in, and it isn’t. It’s the one cost that doesn’t change year to year. Everything below this does.
2. OCA and third-party modules stop shipping for your version
The Odoo Community Association maintains dozens of the modules most SMBs actually depend on — extra accounting reports, industry-specific inventory logic, connector modules for local payment gateways and logistics providers. OCA maintainers don’t support every version forever. In practice, active backporting to a given version tends to taper off within about twelve months of the next major release shipping, and stops entirely a version or two after that. Once that happens, a bug in a module you rely on simply doesn’t get fixed upstream. You either fork and patch it yourself, pay someone to, or quietly stop using a feature you used to have. None of that is visible until the day you actually need the fix.
3. Your OS stops getting security updates underneath Odoo
This is the one almost nobody accounts for. Odoo versions are pinned to specific Python and PostgreSQL versions, and those in turn are pinned to specific OS-level package versions. Odoo 15, for instance, is built against a Python and Postgres generation whose upstream security support windows are now closing or closed. When that happens, the server your ERP runs on is no longer receiving patches for known vulnerabilities in its own runtime — not an Odoo bug, an operating-system-and-language-runtime bug that nobody upstream is fixing anymore. You can keep the box running. You just can’t keep it patched. For a system that holds your customer data, your GST filings, and your payroll, that’s not a theoretical risk.
4. API churn gets worse the longer you wait — not better
This is the one that actually decides your final bill, and it’s the most counter-intuitive. Odoo’s internal APIs shift with every major version — the ORM, view architecture, and JS framework have all had meaningful rewrites across the v15–v20 range. Each version-to-version jump introduces its own set of deprecations. A v15 → v18 migration crosses three of those jumps. Wait two more years and do v15 → v20 instead, and you’re crossing five, plus you’re now migrating custom modules that themselves haven’t been touched or tested against anything newer than v15 for years. The audit takes longer, the rewrite surface is bigger, and there are more places for something to quietly break. Migrating sooner, across fewer version jumps, is mechanically easier work — not just cheaper because you avoided a surcharge.
5. The forced migration is always the expensive one
Nobody migrates off a legacy version on their own schedule when they’ve let it run five years past its support window. They migrate when something breaks and can’t be un-broken — a critical OCA module that finally has no maintained fork, a hosting provider that stops supporting the old Postgres version, a security incident that forces the question. At that point you’re not negotiating a fixed-scope project on your timeline. You’re paying for an emergency, usually during your busiest quarter, with less leverage to say no to scope creep. The teams we’ve seen get the best outcomes are the ones who treated the migration as a planned project years before it became a forced one.
Why parallel-staging beats in-place, especially on old versions
The instinct on an old version is to want to “just upgrade in place” and get it over with. That’s exactly backwards on a legacy jump, because the older your source version, the more custom code and third-party modules are genuinely uncertain to survive the jump untouched. An in-place upgrade takes production down, runs the migration, and finds out what broke with real users watching. A parallel-staging migration stands the target version up alongside your live system, runs your actual customisations and data against it for real, and does a row-level diff before anyone signs off on a cutover date. On a v15-or-older source, that difference isn’t optional polish — it’s the difference between finding a broken custom report during UAT and finding it three days after go-live, mid-invoice-run, with a customer on the phone.
If you’re on v15 or older today, the honest math is this: the surcharge you can already see is the smallest number in this whole equation. The module support you’ll lose, the OS patches you’re no longer getting, and the migration that gets harder every year you wait are the numbers that actually decide what this costs you. None of them show up on an invoice until they do.