---
title: "Top Odoo Alternatives (2026): TCO, Features & Migration Paths"
slug: top-odoo-alternatives-2026-tco-features-migration-paths
date: 2026-08-05
author: Abdul
categories: [ERP, CRM, Migration Guide]
excerpt: "Compare the top Odoo alternatives in 2026 by pricing, architecture, migration complexity, and 3-year TCO. Covers ERPNext, Zoho One, Dynamics 365, NetSuite, Acumatica, and SAP B1."
tldr: "Odoo's Custom plan pricing cliff and API restrictions drive most migrations. ERPNext wins on cost, Zoho One on simplicity, Business Central on enterprise readiness, NetSuite on multi-subsidiary consolidation."
canonical: https://clonepartner.com/blog/top-odoo-alternatives-2026-tco-features-migration-paths/
---

# Top Odoo Alternatives (2026): TCO, Features & Migration Paths


# Top Odoo Alternatives (2026): TCO, Features & Migration Paths

If you're evaluating **Odoo alternatives in 2026**, you've likely hit one of these walls: the jump from Standard to Custom plan pricing just to get external API access, upgrade-path breakage on custom modules between major versions, or the realization that Odoo's open-core model hides critical features behind paywalls that rival the cost of traditional mid-market ERPs.

Odoo is not a bad product. It's a capable ERP with a strong developer community. But the reasons teams migrate away are structural, not cosmetic — and moving off Odoo is a data engineering project, not just a software procurement exercise.

This guide compares six alternatives to Odoo across architecture, real pricing, migration complexity, and total cost of ownership. We cover the specific technical constraints you'll face extracting data from Odoo — including API restrictions and polymorphic data models that most comparison articles ignore — and map out which platform fits which operational profile.

**Disclosure:** This guide is published by ClonePartner, an ERP data migration firm. Pricing figures are sourced from vendor pricing pages and documentation as of Q1 2026. Where pricing is negotiated or range-based, we note this explicitly.

---

## Why Companies Leave Odoo in 2026

### The Pricing Cliff Between Standard and Custom

The Standard Plan ($31.10/user/month in the USA, billed annually) includes cloud hosting and all standard Odoo applications but excludes three capabilities that most growing businesses need: Odoo Studio (no-code customization), multi-company support, and external API access.

Unlocking all three requires the Custom Plan at $61.00/user/month — a **96% per-user price increase**. For a 20-user team, that's $14,640/year versus $7,464/year, a difference of $7,176 annually before implementation costs.

Odoo pricing also varies significantly by geography. The Standard plan ranges from approximately $8.95/user/month in Middle Eastern markets to $76.20/user/month in the USA when billed annually. Budget accordingly — the figure on Odoo's homepage may not apply to your region.

### The External API Lock-In

This is the constraint that catches integration-heavy teams off guard. **Access to the external API is only available on Custom Odoo pricing plans.** The One App Free and Standard plans have no external API access at all.

If you're on Standard and need to connect Odoo to a warehouse management system, a BI tool, or a third-party CRM — you cannot do it via API. You must upgrade to Custom or rely on manual CSV workflows.

Even on the Custom plan, Odoo's API performance has hard ceilings. The rate limit for throttled calls is approximately **1 call/second with no parallel calls permitted**. The standard out-of-the-box API performance cannot handle large data flows combined with intensive concurrent activity. At 1 call/second with batches of 500 records, extracting 100,000 partner records takes approximately 200 sequential API calls — roughly 3–4 minutes for partners alone. A full ERP dataset (partners, products, invoices, journal entries, stock moves) can take hours of wall-clock extraction time. Plan weekend migration windows accordingly.

### Upgrade Path Fragility

Odoo releases a new major version annually. Each new release comes with significant architectural changes: data models and field structures are updated, module business logic is revised, and the behavior of ORM, API, and core framework components is modified. This directly impacts custom modules, integrations, performance, and system stability.

If you use Odoo Community, upgrading means manually migrating your database and refactoring all custom modules. If you use Odoo Enterprise, Odoo provides a database upgrade script, but you remain responsible for updating all third-party and custom code. Odoo's "everything-in-one" approach creates an unintended consequence: updating one module can break another.

Many companies find themselves version-locked on Odoo 14 or 15 because the engineering cost to upgrade simply exceeds the operational tolerance for disruption.

### The Odoo Version Matrix

A structured view of what changed when — critical for migration planning:

| Version | Release Year | API Endpoint | Studio Availability | Notable Schema Changes |
|---|---|---|---|---|
| Odoo 14 | 2020 | XML-RPC only | Enterprise only | `hr.payslip` restructure |
| Odoo 15 | 2021 | XML-RPC only | Enterprise only | `account.move` replaces `account.invoice` |
| Odoo 16 | 2022 | XML-RPC only | Enterprise only | `product.template` variant field changes |
| Odoo 17 | 2023 | XML-RPC only | Enterprise only | Chatter decoupled from core models |
| Odoo 18 | 2024 | XML-RPC + JSON-2 (beta) | Enterprise only | New `mail.thread` mixin architecture |
| Odoo 19 | 2025 | JSON-2 (stable) | Enterprise + Community (limited) | `res.partner` bank account model split |

**Migration implication:** Your extraction scripts must be version-aware. The `account.move` model introduced in Odoo 15 replaced `account.invoice` — scripts written for Odoo 14 databases will fail silently or return empty results on Odoo 15+ instances if not updated.

### Polymorphic Data Structures

Odoo relies heavily on polymorphic data models. `res.partner` stores customers, vendors, employees, and companies in a single table, distinguished by rank fields (`customer_rank`, `supplier_rank`) and boolean flags. While flexible for developers, this creates significant reporting bottlenecks for finance teams trying to isolate specific entity types without writing custom SQL. It also makes data extraction for migration significantly harder — covered in detail below.

---

## Odoo Alternatives Comparison Table (2026)

| Platform | Best For | Pricing Model | Starting Cost (20 users, annual, USA) | External API | Open Source |
|---|---|---|---|---|---|
| **ERPNext** | Cost-conscious SMEs with dev capacity | Free self-hosted; hosted plans available | $0 (self-hosted) | Yes, all plans | Full GPL v3 |
| **Zoho One** | All-in-one SaaS without deep ERP complexity | Per-user (All Employee or Flexible) | ~$8,880/yr | Yes, all plans | No |
| **Dynamics 365 Business Central** | Microsoft-stack mid-market companies | Per-user (Essentials/Premium) | ~$16,800–$24,000/yr | Yes, all plans | No |
| **Oracle NetSuite** | Multi-subsidiary global consolidation | Base platform + per-user + modules | ~$42,840–$59,760/yr | Yes, all plans | No |
| **Acumatica** | High user count, resource-based pricing | Consumption-based, unlimited users | ~$25,000–$45,000/yr | Yes, all plans | No |
| **SAP Business One** | Manufacturing and distribution SMEs | Per-user perpetual or subscription | ~$30,000–$60,000/yr | Yes, all plans | No |

---

## ERPNext: The True Open-Source Alternative

**Best for:** Teams who want a 100% open-source ERP without enterprise paywalls.

ERPNext from Frappe is fully free and open source under GPLv3 with no paid-tier gating — every feature ships out of the box. Where Odoo gates accounting, mobile apps, and Studio behind Enterprise pricing, ERPNext is completely open source. Its open-core competitor (Odoo) requires Enterprise licenses for modules ERPNext includes by default: multi-currency accounting, payroll, manufacturing MRP, and project management.

### Architecture

ERPNext is built on Python and MariaDB, layered on the Frappe framework. Its "DocType" system is metadata-driven: custom fields, workflows, and new document types are defined as database-stored configuration rather than as Python code changes. This means schema customizations survive framework upgrades more reliably than Odoo's Python module approach — though the ERPNext upgrade path between major versions (e.g., v13 to v14) still requires database migration scripts.

**Key architectural difference from Odoo:** ERPNext uses a strict parent-child document model (each DocType is a discrete entity with explicitly defined child tables), whereas Odoo's ORM uses inheritance chains and polymorphic records. This makes ERPNext's schema easier to reason about during migration but less flexible for novel data relationships.

### Ecosystem Trade-offs

The module ecosystem is where Odoo dominates: over 40,000 community apps versus ERPNext's roughly 1,000 published apps. If you need niche industry connectors (e.g., EDI for automotive, 3PL integrations, or HIPAA-specific compliance modules), Odoo's marketplace is deeper. ERPNext's codebase is leaner and the Frappe framework is easier to audit, but the vendor-supported ISV ecosystem is materially smaller.

### Common ERPNext Migration Failure Modes

- **Many-to-many relationships:** ERPNext represents many-to-many links via explicit child table DocTypes. Migrating many-to-many data from Odoo (e.g., product-to-multiple-supplier mappings) requires creating intermediate DocType records, not just field mappings.
- **Naming series conflicts:** ERPNext uses auto-generated naming series (e.g., `INV-2024-00001`) that can conflict with imported historical document numbers from Odoo. Resolve this by disabling auto-naming during import or using a custom naming series prefix for historical records.
- **Custom field migration:** ERPNext custom fields are DocType configurations stored in the database. Migrating Odoo's `x_` prefixed custom fields requires creating corresponding ERPNext Custom Field records before importing data, not just adding column values.

### TCO

Very low licensing cost — you pay only for hosting (Frappe Cloud starts at ~$50/month for small deployments, or self-hosted on a $20–$100/month VPS) and developer time. The hidden cost is internal engineering: ERPNext requires more hands-on maintenance than a fully managed SaaS platform.

**Best fit:** Companies with Python-capable technical teams, under 50 users, and a willingness to invest engineering time in exchange for zero license fees.

**Migration note:** ERPNext's data model is closer to Odoo's than SAP or QuickBooks, which makes field mapping easier. The biggest structural gap is the polymorphic `res.partner` table — ERPNext separates Customers, Suppliers, and Contacts into distinct DocTypes, so Odoo's unified partner table must be split before import.

---

## Zoho One: The SaaS Bundle Play

**Best for:** Teams wanting an all-in-one SaaS suite with minimal implementation overhead.

Zoho One bundles 50+ applications — CRM, accounting (Zoho Books), helpdesk, HR, projects, email hosting — under a single subscription. In 2026, Zoho One pricing has two models:

- **All Employee plan:** ~$37/user/month (annual billing) — requires all employees to be licensed
- **Flexible User plan:** ~$90/user/month (annual billing) — individual user selection

For a 20-person company where all employees need business tool access, the All Employee plan costs $740/month or **$8,880/year** — less than Odoo Custom for 20 users ($14,640/year in the USA).

### Architecture Difference vs. Odoo

Zoho's individual applications are not built on a shared database the way Odoo's are. Data moves between Zoho CRM and Zoho Books through integration middleware and sync logic, not a unified schema. In practice, you will encounter sync lag (typically 15–60 seconds for CRM-to-Books record propagation), and field mapping mismatches between modules require manual configuration. Odoo's single-database architecture is genuinely superior for operational consistency and real-time cross-module reporting.

### Where Zoho One Wins Over Odoo

- **No plan tiers for API access** — REST APIs are available on all Zoho One plans
- **Native integrations** with Shopify, Stripe, PayPal, Slack, Google Workspace, and DocuSign without custom middleware
- **No-code automation** via Zoho Flow (an internal iPaaS) and Deluge scripting
- **Included business email** via Zoho Mail — Odoo requires third-party email hosting

### Common Zoho One Migration Failure Modes

- **Double-entry accounting gaps:** Zoho Books does not support multi-entity consolidation or intercompany eliminations natively. If you're migrating from Odoo multi-company, Zoho Books handles each entity independently — consolidated P&L requires manual export and reconciliation.
- **CRM-to-accounting relationship loss:** Odoo's native CRM-to-invoice link (sales order → invoice → journal entry, all in one schema) becomes a sync relationship in Zoho. Historical opportunity-to-revenue traceability is not automatically preserved on migration.
- **Zoho Analytics as a separate product:** Advanced reporting requires Zoho Analytics (included in Zoho One), but data connectors between Zoho apps and Analytics must be configured separately.

---

## Microsoft Dynamics 365 Business Central: The Enterprise On-Ramp

**Best for:** Companies standardizing on the Microsoft ecosystem and those outgrowing Odoo's accounting and multi-entity limitations.

Business Central is the most commonly cross-shopped alternative to Odoo in the mid-market segment, particularly for companies already using Microsoft 365.

### Architecture

Business Central runs on a multi-tenant SaaS model backed by Azure SQL. Customizations are built in **AL (Application Language)** using an **extension model** — customizations exist as separate packages layered on top of the base application without modifying core code. Microsoft deploys updates monthly; AL extensions that follow proper event subscription patterns are insulated from base application changes.

This is the most important architectural difference from Odoo: **Business Central customizations do not require refactoring during upgrades.** Odoo custom Python modules often break on major version upgrades because they directly modify or inherit from core models. Business Central extensions subscribe to published events and override specific interface points, making upgrade risk structurally lower.

### Pricing (2026, USA)

- **Essentials:** $70/user/month — financials, supply chain, project management, CRM
- **Premium:** $100/user/month — adds Manufacturing and Service Management
- **Team Member:** $8/user/month — read-only plus limited write operations

A 20-user Premium deployment costs **$24,000/year** in licensing. This is $9,360/year more than Odoo Custom (20 users), but the total cost calculus shifts when you factor in:
- Power Platform integration (Power BI, Power Automate) included without additional licensing tiers
- Copilot AI features (cash flow forecasting, late payment prediction, bank reconciliation assist) included
- No separate module fees — Premium includes all manufacturing features

### Common Business Central Migration Failure Modes

- **AL development learning curve:** BC customization requires AL language expertise. Python developers from Odoo cannot directly transition to AL without training. Budget 4–6 weeks of ramp time per developer.
- **Dimension model vs. Odoo analytic accounts:** Business Central uses a "Dimensions" concept for multi-dimensional reporting (equivalent to Odoo's analytic accounts). Migrating Odoo analytic account data to BC Dimensions requires explicit dimension value mapping — there is no automatic equivalence.
- **Inventory costing method lock-in:** Business Central sets the inventory valuation method (FIFO, LIFO, Average, Standard) per item and cannot be changed after inventory transactions exist. Odoo allows more flexible costing reconfiguration. If your Odoo instance uses a mix of costing methods per product category, the BC migration requires careful item-by-item analysis before cutover.
- **Missing Odoo ecommerce/website equivalent:** Business Central has no native website builder or ecommerce module. If Odoo's website or ecommerce capabilities are in use, a separate platform (Shopify, BigCommerce) must be selected and integrated.

### Key Advantages Over Odoo

- Native integration with Microsoft 365, Power BI, Teams, and Azure Active Directory
- AppSource marketplace with thousands of ISV extensions, many industry-specific
- Multi-company support on all plans (Essentials and Premium)
- Full API access on all plans via OData v4 and REST

---

## Oracle NetSuite: The Multi-Subsidiary Standard

**Best for:** Global operations, multi-subsidiary consolidation, and SaaS/subscription billing.

NetSuite is Odoo's opposite in almost every dimension: proprietary, negotiated pricing, and purpose-built for multi-entity consolidation at enterprise scale.

### Architecture

NetSuite runs on an Oracle database in a single-tenant cloud instance. Customizations are written in **SuiteScript 2.1 (JavaScript)**, deployed as Server-Side Scripts, User Event Scripts, or Scheduled Scripts. SuiteScript runs in a sandboxed context that survives NetSuite's twice-annual major updates — custom logic rarely breaks on system updates, unlike Odoo's Python module approach.

The **OneWorld module** (an add-on) enables real-time multi-subsidiary consolidation with intercompany eliminations, multi-currency translation, and consolidated financial statements across legal entities — functionality that Odoo's multi-company feature approximates but does not match for complex global structures.

### Pricing (2026, USA)

NetSuite pricing is negotiated, not published, but the typical structure is:
- **Base platform fee:** ~$999/month ($11,988/year)
- **Per-user fee:** $129–$199/user/month depending on license type and negotiation
- **Module fees:** OneWorld, Advanced Financials, SuiteCommerce, WMS, etc. priced individually

In practice, a 10-user core ERP deployment runs approximately $24,000–$42,000/year. A 20-user mid-market deployment with OneWorld typically runs **$43,800–$59,760/year** in licensing alone — 3–4x Odoo Custom pricing.

**Important:** Oracle raised the base full-user rate from $99 to $129/month (approximately 30%) in recent renewal cycles without advance notice. Factor a 10–15% annual license cost increase into multi-year TCO models.

### Common NetSuite Migration Failure Modes

- **SuiteScript debugging is poor:** NetSuite's development environment lacks the debugging tooling of modern IDEs. Script logs are written to a separate log viewer, not inline. Budget **2x developer hours** compared to equivalent Odoo Python development for custom business logic.
- **Saved Search performance limits:** NetSuite's primary reporting mechanism (Saved Searches) has a 1,000-column and 10,000-row display limit. For finance teams accustomed to Odoo's direct SQL reporting, this requires architectural rethinking.
- **Contract lock-in:** NetSuite contracts are typically 3-year terms with automatic renewal clauses. Exit costs are significant. Review contract language carefully before signing.
- **OneWorld complexity:** Multi-subsidiary intercompany transactions require explicit intercompany elimination setup. Migrating from Odoo multi-company to NetSuite OneWorld is not a lift-and-shift — it requires redesigning your chart of accounts and intercompany transaction workflows.

### When NetSuite Makes Sense Over Odoo

Managing 3+ legal entities across different countries with consolidated financial reporting, multi-currency transactions, and statutory reporting requirements in multiple jurisdictions. OneWorld is battle-tested at this use case in ways Odoo is not.

---

## Acumatica: Unlimited Users, Consumption Pricing

**Best for:** High-volume distributors, manufacturers, and companies tired of per-user licensing.

Acumatica does not charge per user — that is its core pricing differentiator. It uses a resource- and consumption-based model where cost is driven by the applications licensed and a transaction volume tier, with **unlimited users included at every edition**.

### Architecture

Acumatica is built on **C# / .NET**, backed by SQL Server or PostgreSQL, with customizations developed in Visual Studio using standard .NET tooling. REST and OData APIs are available on all plans. The extension framework uses a "graph" model (similar in concept to Business Central's AL extensions) that isolates customizations from core code — reducing upgrade risk compared to Odoo's core-modifying Python modules.

### Pricing (2026, USA)

Acumatica does not publish full pricing. Based on market data:
- **Entry-level (Small Business Edition):** ~$6,396/year (up to 10 named users equivalent, 1,000 monthly transactions)
- **Mid-market:** Most businesses with meaningful transaction volume spend **$25,000–$45,000/year**
- **Implementation:** Typically $60,000–$100,000 for a mid-market deployment

The consumption tiers are not publicly documented. Acumatica partners provide quotes based on projected transaction volumes and licensed application modules (Distribution, Manufacturing, Construction, Field Services). This opacity makes budget modeling harder than Odoo's transparent per-user pricing.

### The Acumatica Advantage for Odoo Migrants

For companies running Odoo with 50+ users across warehouse, field, and back-office teams, Acumatica's unlimited-user model can be materially cheaper than per-seat ERPs. A company with 80 users paying Odoo Custom rates ($61/user/month) pays $58,560/year in licensing; the same company on Acumatica might pay $35,000–$45,000/year for equivalent functionality — depending on transaction volume.

### Common Acumatica Migration Failure Modes

- **Transaction volume misestimation:** If your actual transaction volume exceeds your contracted tier at implementation time, costs scale non-linearly. Audit your Odoo transaction history (sales orders, purchase orders, inventory movements, journal entries) for a full 12-month period before signing an Acumatica contract.
- **Partner dependency:** Acumatica is sold and implemented exclusively through VARs (Value-Added Resellers), not directly. The quality variance between Acumatica partners is high. Select a partner with documented vertical experience in your industry.
- **Smaller ISV ecosystem:** The Acumatica marketplace (approximately 200 ISV solutions) is significantly smaller than Business Central's AppSource or NetSuite's SuiteApp marketplace. Verify that any niche integrations you need (EDI providers, 3PL connectors, industry-specific compliance tools) are available before committing.

---

## SAP Business One: Manufacturing Depth

**Best for:** SMEs that need deep manufacturing, supply chain, and compliance capabilities.

SAP Business One is overkill for a 10-person services company but well-suited for discrete and process manufacturing with 20–250 employees.

### Pricing (2026, USA)

- **Subscription:** ~$100–$150/user/month
- **Perpetual:** ~$3,000–$4,500/user (one-time) plus 20% annual maintenance
- **Implementation:** $30,000–$100,000+ depending on complexity and customization scope

A 20-user subscription deployment runs approximately **$24,000–$36,000/year** in licensing, comparable to Business Central Premium.

### Where SAP B1 Beats Odoo

- **Multi-level BOM management** with phantom assemblies and production variants
- **Batch and serial traceability** across the full supply chain (production → warehouse → customer delivery)
- **Quality management** with inspection steps integrated into goods receipt workflows
- **SAP HANA analytics** for real-time operational intelligence without separate BI infrastructure

### Where Odoo Beats SAP B1

- Lower entry cost and modern consumer-grade UI
- Native ecommerce, website builder, and marketing automation
- Broader application footprint (HR, helpdesk, email marketing) without additional SAP module licensing
- Larger and more active developer community for non-manufacturing extensions

### Common SAP B1 Migration Failure Modes

- **SDK customization complexity:** SAP B1 customizations use the SAP B1 SDK (C# or VB.NET) or the Service Layer (REST API). The SDK has legacy patterns and poor documentation for newer developers. Budget significant ramp time for developers transitioning from Odoo Python.
- **Partner ecosystem quality:** SAP B1 implementation quality varies significantly by VAR. SAP's direct support for B1 is minimal — you are largely dependent on your implementation partner post-go-live.

---

## Feature and Architecture Comparison

| Feature / Platform | Odoo (Enterprise) | Business Central | NetSuite | ERPNext | Acumatica |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **License Model** | Per user + app fees | Per user (Essentials/Premium) | Base + per user + modules | 100% Free / Hosted | Resource/Volume based |
| **Tech Stack** | Python / PostgreSQL | AL / Azure SQL | SuiteScript (JS) / Oracle | Python / MariaDB | C# / .NET / SQL |
| **Customization Approach** | Core-modifying Python modules | Event-based AL extensions | SuiteScript sandbox | DocType metadata + Python | Graph-based .NET extensions |
| **Upgrade Risk** | High (code refactoring required) | Low (extension isolation) | Low (SuiteScript sandbox) | Moderate (migration scripts) | Low (extension isolation) |
| **Multi-Entity** | Custom plan required | Native, all plans | Native (OneWorld add-on) | Native, all plans | Native, all plans |
| **API Access** | XML-RPC / JSON-2 (Custom plan only) | REST / OData v4 (all plans) | REST / SOAP (all plans) | REST (all plans) | REST / OData (all plans) |
| **API Rate Limit** | 1 call/sec, no parallelism | 600 requests/min per tenant | 10 concurrent requests | No published limit | No published limit |
| **User-based pricing floor** | $31.10/user/mo (Standard) | $8/user/mo (Team Member) | ~$129/user/mo | $0 | N/A (volume-based) |
| **Ecommerce / Website** | Native | 3rd party required | SuiteCommerce (add-on) | Basic (Webshop) | 3rd party required |

---

## How to Extract Your Data From Odoo

Migrating away from Odoo is a data engineering problem before it's a platform selection exercise. Odoo's PostgreSQL database is highly relational, and extraction requires handling custom fields, polymorphic tables, and external file storage.

### Method 1: External API (Custom Plan Only)

Odoo supports two API protocols. **XML-RPC** has been available since Odoo 8. **JSON-2** is stable in Odoo 19 and was in beta from Odoo 18. XML-RPC is available on all Odoo versions; JSON-2 requires Odoo 19+.

**XML-RPC example (all supported versions):**
```python
import xmlrpc.client

url = 'https://your-instance.odoo.com'
db = 'your-database-name'
username = 'your@email.com'
api_key = 'YOUR_API_KEY'

common = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/common')
uid = common.authenticate(db, username, api_key, {})

models = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/object')

# Paginated extraction with rate limit handling
import time

all_partners = []
offset = 0
batch_size = 500

while True:
    batch = models.execute_kw(
        db, uid, api_key,
        'res.partner', 'search_read',
        [[['active', '=', True]]],
        {
            'fields': ['name', 'email', 'phone', 'customer_rank',
                       'supplier_rank', 'company_id', 'is_company'],
            'limit': batch_size,
            'offset': offset
        }
    )
    if not batch:
        break
    all_partners.extend(batch)
    offset += batch_size
    time.sleep(1)  # Respect 1 call/second rate limit — no parallelism permitted
```

**JSON-2 example (Odoo 19+ only):**
```python
import requests
import time

url = "https://your-instance.odoo.com/json/2/res.partner/search_read"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
}

all_partners = []
offset = 0
batch_size = 500

while True:
    payload = {
        "domain": [["active", "=", True]],
        "fields": ["name", "email", "phone", "customer_rank",
                   "supplier_rank", "company_id", "is_company"],
        "limit": batch_size,
        "offset": offset
    }
    response = requests.post(url, json=payload, headers=headers)
    response.raise_for_status()
    batch = response.json()
    if not batch:
        break
    all_partners.extend(batch)
    offset += batch_size
    time.sleep(1)  # Respect 1 call/second rate limit
```

> [!WARNING]
> The external API is only available on the Custom plan ($61/user/month in the USA). If you're on Standard, you cannot use this extraction method on Odoo Online. You'll need direct database access (if self-hosted) or negotiate a temporary plan upgrade before migration.

**Rate limit math:** At 1 call/second with batches of 500:
- 100,000 partners = ~200 API calls = ~3–4 minutes
- 500,000 invoice lines = ~1,000 API calls = ~17–20 minutes
- 2,000,000 stock move lines = ~4,000 API calls = ~70–80 minutes

For full ERP extraction across all models, plan 4–8 hours of extraction time on a large database.

### Method 2: CSV/Excel Export (All Plans)

Odoo's built-in import/export handles CSV files up to approximately 50,000 records reliably. The same export functionality is available from any list view on all plan tiers.

**Limitations:** CSV exports flatten relational data. A multi-line invoice becomes multiple rows; the parent-child relationship between invoice header (`account.move`) and invoice lines (`account.move.line`) must be reconstructed in the target system. This reconstruction step is where most manual CSV-based migrations introduce data corruption.

**Specific failure mode:** When exporting `account.move` (invoices), Odoo repeats the invoice header fields on every line. If the header has 3 lines, you get 3 rows with duplicated header data. Import into target systems that expect a header row + child rows (NetSuite, Business Central) requires a de-duplication and restructuring step before import.

### Method 3: Direct Database Access (Self-Hosted or Odoo.sh)

If you're running Odoo on your own infrastructure or Odoo.sh, you have direct PostgreSQL access. This is the fastest extraction method and bypasses API rate limits entirely.

```sql
-- Split res.partner into customers, vendors, and companies
-- Customer extraction
SELECT 
    rp.id,
    rp.name,
    rp.email,
    rp.phone,
    rp.street,
    rp.city,
    rp.zip,
    rc.name as country,
    rp.customer_rank,
    rp.vat as tax_id,
    rp.company_id,
    rp.is_company
FROM res_partner rp
LEFT JOIN res_country rc ON rc.id = rp.country_id
WHERE rp.customer_rank > 0 
  AND rp.active = true;

-- Vendor extraction (note: same table, different filter)
SELECT 
    rp.id,
    rp.name,
    rp.email,
    rp.phone,
    rp.supplier_rank
FROM res_partner rp
WHERE rp.supplier_rank > 0 
  AND rp.active = true;

-- Invoice header + lines (Odoo 15+, uses account.move)
SELECT 
    am.name as invoice_number,
    am.invoice_date,
    am.invoice_date_due,
    am.move_type,
    am.amount_untaxed,
    am.amount_tax,
    am.amount_total,
    am.payment_state,
    rp.name as partner_name,
    aml.name as line_description,
    aml.quantity,
    aml.price_unit,
    aml.price_subtotal,
    aa.code as account_code
FROM account_move am
JOIN res_partner rp ON rp.id = am.partner_id
JOIN account_move_line aml ON aml.move_id = am.id
JOIN account_account aa ON aa.id = aml.account_id
WHERE am.move_type IN ('out_invoice', 'out_refund')
  AND am.state = 'posted';
```

> [!WARNING]
> **For Odoo 14 and earlier:** The invoice model is `account.invoice` (not `account.move`). Queries written for Odoo 15+ will fail on Odoo 14 databases. Always confirm your Odoo version before writing extraction queries.

> [!WARNING]
> **Bulk extractions:** For databases with millions of journal entries (`account.move.line`), bypass the API entirely. Run a `pg_dump` of the PostgreSQL database to a staging environment, then run transformation queries locally without network overhead or API rate limits.

### Key Migration Challenges

#### Splitting the Polymorphic `res.partner` Table

Odoo stores customers, vendors, employees, and companies in a single `res.partner` table. The differentiation fields are:

| Field | Type | Meaning |
|---|---|---|
| `customer_rank` | Integer | > 0 = is a customer; higher = more orders |
| `supplier_rank` | Integer | > 0 = is a vendor/supplier |
| `is_company` | Boolean | True = company record; False = contact person |
| `company_id` | Many2one | Links a contact to its parent company |
| `employee` | Boolean | True = also an employee record |

When migrating to strict ERPs like NetSuite or Business Central (which have separate Customer, Vendor, and Contact entities), you must write extraction scripts that split `res.partner` using these fields. A single Odoo partner can be simultaneously a customer (`customer_rank > 0`) and a vendor (`supplier_rank > 0`) — in NetSuite, this requires creating separate Customer and Vendor records linked by an external reference. Failure to handle this correctly results in missing vendor records or duplicate contacts in the target system.

#### Extracting Attachments from the Odoo Filestore

Odoo does not store PDFs, images, or documents inside PostgreSQL by default. The `ir.attachment` table stores metadata including a SHA-1 hash of the file content. The physical files live on disk at:

```
/home/odoo/.local/share/Odoo/filestore/{database_name}/{hash[:2]}/{hash}
```

Where `{hash [:2]}` is the first two characters of the hash (used as a directory shard). Your migration script must:

1. Query `ir.attachment` for all relevant attachments (filtered by `res_model` and `res_id`)
2. For each record, compute the file path using the `store_fname` field
3. Copy or stream the physical file from disk
4. Rename the file to its original name (`datas_fname` or `name` field in the attachment record)
5. Upload to the target ERP via its document management API

```sql
-- Get all invoice attachments with their file paths
SELECT 
    ia.id,
    ia.name,
    ia.store_fname,
    ia.res_model,
    ia.res_id,
    ia.mimetype,
    am.name as invoice_ref
FROM ir_attachment ia
JOIN account_move am ON am.id = ia.res_id
WHERE ia.res_model = 'account.move'
  AND ia.store_fname IS NOT NULL  -- NULL means stored in DB as base64, not filestore
ORDER BY am.name;
```

#### Handling Custom Models and `x_` Fields

Fields created via Odoo Studio or the developer field creator are prefixed with `x_`. Before extracting data, generate a complete data dictionary:

```sql
-- Get all custom fields in the environment
SELECT 
    imf.model,
    imf.name as field_name,
    imf.field_description,
    imf.ttype as field_type,
    imf.required,
    imf.store
FROM ir_model_fields imf
JOIN ir_model im ON im.id = imf.model_id
WHERE imf.name LIKE 'x_%'
  AND imf.store = true
ORDER BY imf.model, imf.name;
```

Custom fields not captured in this inventory are routinely lost in migrations. Run this query before beginning any extraction work and distribute the output to the business team for field-by-field mapping decisions.

#### Version-Specific Schema Differences

| Business Object | Odoo 14 Table/Field | Odoo 15+ Table/Field | Impact |
|---|---|---|---|
| Invoices | `account.invoice` | `account.move` (move_type filter) | Extraction query rewrite required |
| Invoice lines | `account.invoice.line` | `account.move.line` | Foreign key changes |
| Payments | `account.payment` | `account.move` (payment journal entries) | Complex reconciliation logic |
| Email messages | `mail.message` (chatter linked to model) | `mail.thread` mixin architecture (v18+) | Chatter history extraction changes |

### Import Order Matters

Regardless of your target platform, load data in dependency order to avoid foreign key failures:

1. **Chart of Accounts** — map Odoo's account types to the target system's account structure; all journal entries depend on this
2. **Tax configurations** — tax codes must exist before invoices are imported
3. **Contacts/Partners** — customers, vendors, and companies (split from `res.partner`); all transactions reference these
4. **Products** — including variants, BOMs, units of measure, and product categories
5. **Open transactions** — unpaid invoices, open POs, pending sales orders, unreceived goods
6. **Historical transactions** — closed invoices, completed orders (often archived rather than migrated)

> [!TIP]
> Most Odoo-to-ERP migrations do not move closed historical transactions. They are kept in Odoo or exported to flat files as an archive, while only open balances and active records move to the new system. This cuts migration scope by 60–80% and reduces cutover risk substantially. Agree on the historical data cutoff date with the finance team before extraction begins.

---

## TCO Comparison: 20-User Team Over 3 Years

This model assumes a mid-market company with 20 ERP users, standard modules (financials, CRM, inventory, purchasing), annual billing, and US pricing. All figures are estimates; actual costs vary based on complexity, customization, and implementation partner.

| Cost Component | Odoo Custom | ERPNext (Self-Hosted) | Zoho One | Business Central Premium | NetSuite |
|---|---|---|---|---|---|
| **Year 1 License** | $14,640 | $0 | $8,880 | $24,000 | ~$43,800 |
| **Year 2–3 License** | $29,280 | $0 | $17,760 | $48,000 | ~$87,600 |
| **Implementation** | $15,000–$45,000 | $10,000–$30,000 | $5,000–$15,000 | $30,000–$80,000 | $50,000–$150,000 |
| **Hosting (if applicable)** | Included | $3,600–$7,200 | Included | Included | Included |
| **3-Year TCO Range** | $59K–$89K | $14K–$37K | $32K–$42K | $102K–$152K | $181K–$281K |

**Scenario anchoring:** These ranges assume a single-entity 20-user manufacturing or distribution company, one primary geographic location, no EDI requirements, standard implementation (no custom integrations beyond the platform's native API), and one implementation partner engagement. Adding multi-entity, EDI, or custom integrations increases implementation costs by $20,000–$80,000 for any platform.

> [!NOTE]
> These figures cover licensing, implementation, and hosting. They exclude internal labor (typically 0.25–0.5 FTE dedicated during implementation), training ($500–$2,000/user for enterprise platforms), and ongoing customization maintenance. Internal engineering costs are highest for ERPNext and Odoo (most hands-on) and lowest for Zoho One and NetSuite (most managed). For accurate TCO, add 15–25% to the above ranges to account for internal resource costs.

---

## Decision Framework: Which Odoo Alternative Fits?

**Stay on Odoo if:** You have internal Python developers, your customization needs are well-served by the 40,000+ module ecosystem, and you're comfortable on the Custom plan. Odoo remains the best feature-per-dollar ratio for teams that can self-manage technical operations and are running a single legal entity.

**Choose ERPNext if:** You want zero license fees, your team writes Python, you're under 50 users, and you can accept a smaller ISV ecosystem. The TCO advantage is material — $14K–$37K over 3 years versus $59K–$89K for Odoo Custom — but you're trading ecosystem breadth and vendor support for cost savings.

**Choose Zoho One if:** You want an all-in-one SaaS suite with minimal implementation overhead, your operational complexity does not require multi-entity consolidation, deep manufacturing workflows (multi-level BOMs), or advanced warehouse routing, and cross-application sync lag of 15–60 seconds is acceptable.

**Choose Business Central if:** You're running on or standardizing the Microsoft stack, need strong financial reporting with Power BI integration, require multi-company support without plan upgrades, and want a platform with a clear AI roadmap (Copilot features in production as of 2025). The upgrade from Odoo to BC increases licensing cost but substantially reduces upgrade-related engineering risk.

**Choose NetSuite if:** You're managing 3+ legal entities across multiple countries, need real-time intercompany consolidation and multi-currency statutory reporting, and can absorb the 3–4x licensing premium over Odoo Custom. Do not use NetSuite for a single-entity business — the cost-to-complexity ratio is unfavorable.

**Choose Acumatica if:** Your user count is high relative to your transaction volume (typically >40 users), you want to eliminate per-seat licensing entirely, and you operate in distribution, manufacturing, or construction where Acumatica's vertical editions are mature. Verify your projected annual transaction volume before signing — consumption tier overages are the primary budget risk.

---

## What Migration from Odoo Actually Takes

Based on observed ERP data migration projects, Odoo extraction efforts share a common profile:

**Timeline:**
- Data discovery and schema analysis: 1–2 weeks
- Extraction script development and testing: 1–2 weeks
- Data transformation and mapping: 2–4 weeks
- Target system import and validation: 2–4 weeks
- UAT and cutover: 2–4 weeks
- **Total:** 8–16 weeks for a 20-user mid-market deployment

**Most common failure points (in order of frequency):**
1. Invoice-line relationship loss during CSV-based migrations (`account.move` header/line flattening)
2. Polymorphic `res.partner` table not split correctly — vendors or contacts missing in target system
3. Filestore attachment extraction skipped — historical documents lost after cutover
4. Custom `x_` fields not inventoried — business-critical data silently dropped
5. Version-specific schema differences not accounted for — extraction queries fail or return wrong data
6. BOM parent-child structures collapsed — manufacturing teams lose recipe history

**Cost:** For a 20-user mid-market deployment, budget $10,000–$50,000 for data extraction, transformation, validation, and import. This is separate from the target platform implementation cost.

The software selection is only the first step. Migration success depends on accurately mapping Odoo's polymorphic tables and nested relational structures to your new ERP's schema — and validating every record before cutover.

---

*For architecture comparisons and migration paths between specific alternatives, see: [Acumatica vs NetSuite](https://clonepartner.com/blog/blog/acumatica-vs-netsuite-the-ctos-2026-erp-evaluation-guide/) · [NetSuite vs SAP Business One](https://clonepartner.com/blog/blog/netsuite-vs-sap-business-one-the-2026-architecture-guide/) · [SAP Business One to Business Central](https://clonepartner.com/blog/blog/sap-business-one-to-business-central-the-2026-migration-guide/)*

## Frequently asked questions

### What is the best free alternative to Odoo in 2026?

ERPNext is the strongest free alternative. It's fully open source under GPLv3 with no paid tier — every feature is available out of the box. Self-hosted deployments cost $0 in licensing. The trade-off is a smaller app ecosystem (~1,000 apps vs. Odoo's 40,000+) and a steeper requirement for internal Python developers.

### Can I use the Odoo API on the Standard plan?

No. Odoo's external API (both XML-RPC and the newer JSON-2 endpoint) is only available on the Custom plan, which costs $61/user/month in the USA. The Standard plan at $31.10/user/month does not include external API access. You can still use CSV export on all plans.

### How much does it cost to migrate from Odoo to another ERP?

Expect $10,000–$50,000 for a 20-user mid-market deployment, covering data extraction, transformation, validation, and import. The biggest cost driver is relational data mapping — flattening Odoo's PostgreSQL schema into the target system's structure while preserving invoice lines, BOM hierarchies, and attachment links.

### Why do custom modules break during Odoo version upgrades?

Odoo introduces significant core API, ORM, and data model changes between major annual releases. Custom Python modules built for one version will generally not work on the next without manual code refactoring. The everything-in-one architecture also means updating one module can break another.

### What is the biggest risk when migrating away from Odoo?

Relational data loss. Odoo stores data in a normalized PostgreSQL schema with many-to-many and one-to-many relationships (invoice lines, stock move links, BOM components). CSV exports flatten these relationships, and if your migration process doesn't reconstruct them in the target system, you'll lose critical business context.
