Odoo custom module development

Custom Odoo modules give you behavior that configuration cannot provide, but every module becomes code you must port at each upgrade. This guide covers the decisions, build sequence, tests and upgrade cost so you can scope the work.

On this page

When Odoo custom module development is the right answer

Build a custom Odoo module when a business process cannot be modeled with configuration, the apps already installed, or Odoo Studio, and the gap is central to how the organization works rather than a cosmetic preference. Typical signals include a approval chain with rules that depend on data from several apps, a regulated calculation that the standard models do not hold, or an integration that needs its own data structures. Before deciding, write down each requirement, the configuration option you tried or ruled out, and the business owner who will sign off the behavior. That list is the input any in-house team or partner will need to estimate the work honestly.

A custom module is a Python package that adds models (database tables and business logic), views (XML definitions of forms, lists and menus), security rules (access rights in CSV files and record rules), and tests. Most real modules also inherit core models, meaning they extend a standard model such as sale orders or invoices with new fields and methods instead of copying it. Inheritance is the reason custom work is harder than it looks: each override depends on the internal structure of a core module that Odoo changes between versions. Ask who on your team can read and review that code, and whether the test suite would catch a broken behavior after an upgrade.

Be clear about ownership. Once a module is written, the organization owns that code and must carry it forward at every major version. Odoo's standard support covers the first three years after a major release, and major upgrades are mandatory every two years on Odoo Online and Odoo.sh according to Odoo's upgrade documentation. Each upgrade means porting custom modules to the new API, re-running tests against an upgraded test database, and fixing what breaks. Ask any partner to state in the written scope how ported modules will be tested, who fixes regressions, and whether the port is included or priced separately.

Plan the hosting edition before you commit. Odoo's pricing page places custom modules in the Custom plan, which is also the only plan that can run on Odoo.sh or on-premise, according to that page. Confirm the current plan terms directly with Odoo, because pricing and plan contents change. The Community edition is licensed under LGPL-3.0 and lets you write modules, but Community users have no access to the upgrade service, which removes the supported path to new versions. Treat that as a cost of ownership question: a module you cannot upgrade through a supported route is a module you will eventually rewrite.

Finally, decide who will maintain the code after go-live. Choose between an internal developer team, a partner under a support retainer, or a mix, and write down which party reviews changes, runs tests, and approves releases. Agree on a rule for when a requirement should be dropped rather than built, such as when a later Odoo version already provides the behavior. A short written decision record for each module will save significant effort at the next upgrade.

Which Odoo parts a custom module touches

A custom Odoo module is a folder of declared parts that the server loads in order, and each part changes a different layer of the application. The cards below cover the building blocks a module contains, the two inheritance mechanisms that let it extend core code, and the layers it can reach. Reviewing these parts one at a time is the fastest way to judge how much a module will cost to keep working through each version upgrade.

Manifest and dependencies

The manifest is the module's declaration file. It names the module, its version, and the modules it depends on, and Odoo uses those dependencies to decide load order and which core code the module can inherit. Check that every dependency is listed, because a missing one often works in a test database and fails on a fresh install. Review the dependency list at each upgrade, since core modules can change between versions.

Python models and the ORM

Models are Python classes that describe business objects, their fields and their behavior, and the ORM maps them to PostgreSQL tables. Most custom logic lives here, so this is where bugs in computed fields, constraints and access to records are most expensive to find later. Ask who owns each model, whether it adds stored data, and whether its methods run in loops that could slow large databases.

XML views and actions

XML files define how records appear on screen: form, list and search views, plus the actions that open them. Views are where most user-facing change happens, and they are also the part most likely to break when a core view is restructured. Keep custom views small, name them clearly, and record which core view each one extends so the upgrade team can find it.

Menus and navigation

Menu items place actions into the application navigation and control which users see them. A menu can be hidden from users who lack a group, but hiding it does not stop access through a direct URL. Pair every menu entry with the access rules that actually protect the data behind it.

Access control lists and record rules

Access control lists grant create, read, write and delete rights per model and group. Record rules narrow those rights to specific records, for example by company or by owner. Security problems in custom modules usually come from a model that has no access entry or an overly broad rule, so review both for every new model before testing the feature.

Data files and default records

Data files load XML or CSV records such as groups, sequences, default settings and demo content when a module installs or updates. Separate demo data from data that must exist in production, since demo records should not reach a live database. Check which files run on update, because a change that is safe on install can overwrite customer settings on upgrade.

Model and view inheritance

Model inheritance lets a custom module add fields or methods to an existing core model without copying its code. View inheritance lets it insert or change elements of a core view by reference to an existing view identifier. Both keep the core code untouched, which is why they are the safer choice, but each depends on names in the core code that can change between versions, so each inheritance point is a future porting task.

Layers a module can extend

A custom module can extend four core layers: models, views, reports and scheduled actions. Models hold the business rules, views control the screens, reports control printed or PDF output, and scheduled actions run background jobs on a timer. Decide which layer each requirement truly needs, because a change in a report or cron job is often easier to port than a deep model change.

Tests and their limits

Tests run the module's code against a database and catch regressions when the module or core code changes. Automated tests show that a flow works on the versions and data they were written for, but they do not prove that access rules or reports look right to users. Ask for tests covering access rules, computed fields and inherited views, and confirm which test runner and database setup your team will use.

Security review of custom code

Every custom module is code that runs with the privileges of the server and can read or change data across the database. Review the code for unsafe queries, sudo calls and file access before installation, and confirm who signs off on it. Treat the review as a recurring gate, since each new module or inherited change adds to the surface that must be checked at every upgrade.

Build the module, configure it, or use Odoo Studio

This table compares four ways to change Odoo: configuration, Odoo Studio, a custom module that inherits core code, and a standalone module or external service. Read each row against the change you need, then check the operating cost columns before committing to a build. The main takeaway is that the cheapest option to build is not always the cheapest to upgrade and maintain.

OptionWhen it fitsUpgrade and maintenance effortDependence on plan or team
ConfigurationSettings, workflows, sequences, access groups and existing app options that Odoo already exposesLow; changes are stored as data and usually survive version upgrades with review of settingsAny administrator can make changes; no code review or plan-specific features required
Odoo StudioAdding fields, simple views or basic automations on models where a no-code change is enoughModerate; Studio customizations must be checked after each major upgrade and can conflict with later core view changesRequires the Custom plan according to Odoo's pricing page; works best with a named admin who documents each change
Custom module inheriting core codeChanging core behavior, extending views with logic, overriding methods or adding validation tied to existing modelsHigher; inherited methods and view IDs must be ported at each version upgrade and tested on an upgraded test databaseRequires Python and Odoo framework skills plus code review; needs the Custom plan for custom modules on Odoo.sh or on-premise
Standalone module or external serviceNew business logic or a new data model that does not belong inside core models, or work that calls out to another systemVaries; a standalone module has fewer core conflicts, but the integration contract, API versions and data sync need their own testing each releaseNeeds ownership by a named team with tests and runbooks; external services add hosting and security review outside Odoo
Typical signal to build a moduleSeveral Studio or configuration changes depend on hidden logic, or a feature needs new models, scheduled actions or reportsPlan for a port of each module at every major version within standard supportConfirm with Odoo's pricing page and your environment whether custom modules are available on your intended hosting

How to build an Odoo custom module step by step

This sequence turns a business requirement into a tested, reviewable Odoo module that installs cleanly, respects access rights and can be deployed without surprises. Each step closes with a check the reader can verify before moving on.

  1. Define the business rule and data model

    Start by writing down the business rule the module must enforce, the records it touches and the existing Odoo models it relates to. Confirm with the process owner which fields are new, which already exist on core models, and which should be handled by configuration or Odoo Studio instead of code. Decide early whether the change extends a core model or adds a new one, because that choice drives every later step. The step is done when the rule, the fields and the related models fit on one page and the business owner has signed off on them.

  2. Scaffold the module with manifest and dependencies

    Create the module folder with a manifest file that declares its name, version, category, license and dependencies. List only the modules the code actually uses, because every unnecessary dependency makes installation and future upgrades harder. Match the version string to the target Odoo release so the module is clearly tied to one major version. The step is closed when the module appears in the Apps list of a development database and installs without errors on an empty instance.

  3. Write models with fields and constraints

    Implement the Python model classes, defining fields, computed values, onchange logic and constraints that enforce the business rule at the database and application level. Inherit existing core models where possible rather than copying them, and keep overrides narrow so they survive future upgrades. Add SQL or Python constraints for rules that must never be broken, not only warnings in the interface. The step is closed when a developer can create, edit and delete records from the shell and the constraints reject invalid data as intended.

  4. Add views and menus

    Build the XML views the users will see: forms, lists, search views and the menu items that open them. Extend existing core views through inheritance with xpath expressions, so the module adds fields without replacing whole screens. Check the layout with a real user role, not only an administrator account, because menus and buttons often appear differently for restricted users. The step is closed when a test user can reach every new screen from the menu and complete the main task without developer tools.

  5. Set access rights and record rules

    Define which groups can read, create, write and delete each new model in the access rights file, and add record rules where access depends on the record, such as company, team or owner. Assign groups to menus and actions so the interface matches the permissions. Default to least privilege and grant anything broader only when a named role needs it. The step is closed when a user without rights cannot read a restricted record through the interface, a list view, an export or a direct URL, and a user in the correct group can.

  6. Write data and demo files

    Add data files for records the system needs at install time, such as sequences, default configuration or lookup values, and separate demo files for sample records used in training and testing. Keep data files idempotent and keyed by stable external IDs so updates from later module versions do not duplicate records. Keep demo data out of production installs by flagging it as demo. The step is closed when the module installs on an empty database with the demo flag off and no unexpected records appear, and with the flag on the demo records load without errors.

  7. Add automated tests

    Write tests with Odoo's test framework covering the business rule, the constraints, the access rules and the main workflow end to end. Include negative tests that confirm invalid data is refused and restricted users are blocked, since those are the failures auditors and users find first. Run the suite on a clean database and again after installing the module on top of other modules it depends on. The step is closed when the full suite passes repeatedly from a clean start and a failing rule causes a visible test failure.

  8. Review, package and deploy to a neutralized copy

    Have a second developer review the code for upgrade risk, security issues, hard-coded values and overrides of core methods, and record the findings with their resolution. Package the module in the agreed format, then install and test it on a neutralized copy of production, which keeps the data shape but disables outgoing mail, payments and integrations. Confirm the upgrade path to the next supported version before go-live, because custom code must be ported at each major upgrade. The step is closed when the review findings are resolved, the neutralized-copy test passes with the business owner's sign-off, and the deployment steps are documented for the operations team.

How to inherit core Odoo modules without forking them

The safest way to change core Odoo behavior is to extend the core models and views through inheritance, not to copy core files into a fork. In Odoo, a custom module declares the model it extends with an inheritance attribute, adds fields or methods, and leaves the original module untouched. The core code keeps receiving vendor fixes and version changes, and your custom layer sits on top of it. A fork, by contrast, freezes a snapshot of core code inside your repository, so every security fix and bug fix has to be merged by hand. For a self-hosted deployment, where you own the upgrade calendar, that manual merge is usually the largest recurring cost of custom work.

Inheritance has its own failure modes, and most of them come from method overrides. When you override a core method, you replace the logic that the original method runs, including checks, computed values and side effects that other modules may depend on. Calling the parent with super() keeps that logic in place. Review every override for three things: whether it calls the parent, whether it passes the same arguments and return value, and whether it runs the extra logic before or after the core step that the core module expects. An override that omits the parent call can silently skip stock moves, accounting entries or access checks, and the bug may only appear in a workflow nobody tested.

Dependencies on internal field names and XML IDs are the second source of upgrade cost. A custom domain, a computed field or a server action that refers to an internal field name will break if the core model renames or removes that field in a later version. The same applies to XML IDs, which your module uses to reference core views, menus, actions and security groups. Each reference you add is a point that can fail on upgrade. Keep a written list of every core field, method, view and XML ID your modules touch, and record why each one is needed. That list becomes the first input to the review you run before each upgrade.

Inherited views are the most visible point of breakage. An inherited view uses an XPath expression to locate and modify elements in the core view. When the core view changes its structure, for example by moving a group, renaming a tab or wrapping a field in a new container, the XPath may match nothing or match the wrong node. Odoo can raise an error at install time or, worse, place your field in an unintended location without raising any error. Use the most stable anchors available, such as field names rather than positional selectors, and check each inherited view against the new core structure after every version change.

Two practices control this cost over time. First, review each inherited method and XML ID as part of every upgrade, using a checklist that compares the core source of the target version with your overrides and references. Second, keep the number of inherited core points small. Each additional override or view extension is another item in that review, and another item that can break. Before adding one, ask whether a configuration setting, a standard feature or a separate custom model would meet the requirement. Ask your implementation partner to show the inherited points in a written inventory with each upgrade estimate, so you can see the maintenance load before the build starts.

What drives the cost of a custom Odoo module

This table lists the main effort drivers behind a custom Odoo module and what each one costs in developer, review, testing and porting time. Read each row as a lever: the middle column explains why the driver grows effort, and the right column shows how to keep it contained. The main takeaway is that scope decided early in the specification matters more than the number of lines written later.

DriverWhy it changes effortHow to keep it down
Number of models and business rulesEach model needs fields, access rules, constraints, tests and migration handling, and business rules interact with each other and with core flows.Write a short data model and rule list before coding, and drop rules that standard configuration already covers.
Depth of core inheritanceDeep inheritance of core classes ties the module to internal method signatures that change between versions, so every upgrade needs more porting.Inherit at the narrowest point, prefer new models linked to core records, and avoid patching several layers of the same core class.
Overridden core methodsEach overridden method is a copy of core logic that must be re-checked when Odoo changes it, and overrides can conflict with other modules.Call super, keep overrides short, and replace an override with a hook or an extension point where the core offers one.
Number of views, reports and print outputsEvery form, list, search view, QWeb report and PDF output needs layout work, testing across roles and browsers, and maintenance at upgrade.Extend existing views with small XPath changes, reuse standard report templates and limit custom outputs to documents the business requires.
Integrations with external systemsEach connection needs authentication, data mapping, error handling, retries, duplicate prevention and monitoring, usually the largest source of unplanned work.Agree the data direction, source of truth and failure behavior for each integration in writing, and build one integration per external system where possible.
Data volume and migrationLarge or dirty datasets require import scripts, batch processing, performance checks on a production-sized copy and reconciliation after load.Ask for a sample extract early, define which history is migrated, and budget a test load on a copy of production before the build is final.
User roles and record rulesEach role needs access rights, record rules and menu visibility, and each combination must be tested because mistakes expose data.Map roles to existing Odoo access groups first and add record rules only where a real data boundary exists.
Environments (development, test, production)Each environment needs its own configuration, data, deployment steps and sign-off, and differences between them cause failed releases.Agree the number of environments and the deployment method in the plan, and keep configuration in version control so environments match.
Number of Odoo versions to supportCode written for one major version often needs changes for the next, so every supported version adds a porting and retesting cycle.Confirm the target version and its support window at the start, and plan the next upgrade against the standard support dates for that version.

How to test an Odoo module and make it fail safely

A custom Odoo module should be tested in layers, and each layer should be designed to catch a specific kind of failure before the module reaches production. The first layer is Odoo's built-in test framework, which runs Python test classes against the module's models and methods. These tests should cover computed fields, onchange logic, constraints and any server actions the module adds. For access control, write tests that run the same operation as different users, such as a sales user, a warehouse user and a user with no group membership, and assert which records are visible, editable or denied. Access rights and record rules are easy to get wrong because they often look correct in the interface while still exposing records through a related model or an API call.

The second layer tests installation and views on a copy of the database, not on an empty development instance. Odoo documents database duplication with neutralization for test copies, which keeps production data available for realistic checks without sending email or triggering live integrations from the copy. Install the module on that copy, upgrade it, and then uninstall it to confirm the uninstall path does not leave orphaned views or broken menus. Check every view that your module inherits from a core view. When Odoo changes the core view's structure in a later release, an inherited view can stop matching its XPath expression, and the failure appears only when a user opens that form. Keep a list of inherited views and their target XPaths so the review can confirm each one still matches after a core change.

The third layer is upgrade rehearsal. Odoo's upgrade service creates an upgraded test database that should be tested before production, and the same discipline applies when you port a custom module to a newer version by hand. Run the module's tests on the target version, then check business-critical flows end to end, including invoices, stock moves or payroll runs, depending on the module's scope. Measure the time these flows take on a copy of production volume. A computed field that stores a value over a large table, or a search that loops over records in Python instead of using a domain, can pass every functional test and still make a daily process unusable. Record timings before and after the change so a regression is visible as a number rather than a complaint.

Before merge, use a written code review checklist. It should confirm that every new model has access rules for each group, that no sudo call bypasses a record rule without a documented reason, that inherited views use stable XPath targets, that computed fields with heavy dependencies are stored only when needed, and that the manifest declares every dependency. Staging sign-off should follow, with named approvers from the business and from IT. Production deployment should wait for that sign-off, and the change record should state the database backup taken immediately beforehand. Confirm with your Odoo partner or internal team how the backup and restore process will be run on your hosting model, since on-premise, Odoo.sh and self-hosted setups differ.

Plan rollback before the deployment, not during it. The practical options are restoring the pre-deployment database backup, redeploying the previous version of the module code while keeping the data, or disabling a feature through configuration while the fix is prepared. Each option has a cost. A database restore discards transactions entered after the backup, so the business must agree on a cutoff and a process for re-entering them. Rolling back code without the data can fail if the new version has already changed the schema or migrated records. Write down which option applies to each change, who can authorize it, and how long a restore takes on your environment, and rehearse one restore on a copy before go-live.

How to secure custom code in Odoo

Custom modules run with the same database, permissions and business data as the core Odoo applications, so a weak control in your code can expose everything else. The controls below are the ones a reviewer should look for before a module reaches production and again at each version upgrade.

Access control lists per model

Every custom model needs explicit access rights in its security CSV file, set per group for read, write, create and delete. A reviewer should confirm that no model is left without rules, that rights are granted to the narrowest group that needs them, and that the file loads on a fresh install and after an upgrade.

Record rules for row-level access

Access rights decide which models a user can touch, but record rules decide which rows. For custom models that hold customer, employee or financial data, check that domain rules restrict records by company, salesperson, department or other ownership fields, and that multi-company rules are not accidentally bypassed.

Careful use of sudo

Sudo runs code with superuser rights and skips access checks, so each call should be justified in code review. Reviewers should check that sudo is limited to the specific read or write that needs it, that the calling user's identity is still validated, and that sudo is never applied to a recordset built from unvalidated user input.

Safe handling of user input

Controllers, website pages and QWeb views can receive data from browsers and external callers. Check that route types and authentication settings are deliberate, that parameters are typed and validated before use in queries or domains, and that values are escaped in templates rather than marked safe without a reason.

No secrets in code or data files

API keys, passwords and tokens should never sit in Python source, XML or CSV data files, or demo data, because these travel with the repository and sometimes into database dumps. Reviewers should search the module for credentials and confirm that secrets come from the server configuration or a secrets store managed by your team.

Review of third-party modules

Modules from app stores or community repositories run with the same privileges as your own code. Before installation, check the license, the publisher, the declared dependencies, any use of sudo or external network calls, and whether the module has been ported to the exact Odoo version you run.

Source control for custom modules

Keep each custom module in a versioned repository with protected branches, mandatory peer review and tagged releases that match deployed versions. Reviewers should be able to trace which commit is running in production, and the same history should support rollback and the port of the module at each Odoo upgrade.

What to maintain, document and port after go-live

The owning team needs three standing assets after go-live: a module register, automated tests against a current database, and a porting plan for each major Odoo version. Without them, the first upgrade becomes a discovery exercise. Start the register on day one. For each custom module, record its technical name, the Odoo version it targets, its declared dependencies, every core model, view or method it inherits or overrides, the owner who approves changes, and whether it depends on any third-party module. Inheritance points are the highest-risk entries, because a core change in a later release can silently break an override that looked harmless at go-live. Tests are the second asset. Keep a test database that is refreshed from production with personal data neutralized, and run the module test suite against it after every change and before every upgrade. Odoo's test framework covers model logic and access behavior when tests are written for them, so record which security rules, record rules and workflows each test exercises. Ask the implementation partner to hand over the test runner setup and to document which tests were written by the project and which were inherited from the original code, so the owning team knows where coverage is thin. Upgrade timing is the third asset, and it is not optional. On Odoo Online and Odoo.sh, major version upgrades are mandatory every two years according to Odoo's upgrade documentation. Standard support covers the first three years after a major release, including security updates and bug fixes. Odoo 19.0 was released in September 2025 with standard support planned until September 2028, and Odoo 18.0 until September 2027, so confirm the current support table before you plan. The upgrade service moves a database to a newer supported version through an upgraded test database, which should be tested before production. Plan a porting budget for each version: every custom module needs review against the new core, and the cost of that work is the main recurring cost of custom code. At project end, request a handover package with these items: the source code in your own version control, install and upgrade notes that cover dependencies and configuration, the test results with the commands used to reproduce them, and documentation of access rules that lists each group, its menu and record access, and the record rules that restrict it. Confirm in writing who holds the repository, the database credentials and the Odoo subscription or hosting account, since those access paths are needed for any upgrade. Ask whether the handover includes a walkthrough of the module register with the owning team.

Questions buyers ask about Odoo custom module development

How much does an Odoo custom module cost to build?

Cost depends on the functional scope, the number of models and views, the integrations involved and how much testing the module needs, so no single figure applies to every module. A partner should price it from a written scope, itemizing requirements analysis, design, Python development, XML views, security rules, automated tests, code review, deployment to a test environment, and fixes after user acceptance testing. Ask for each item separately, state whether the price is fixed or time and materials, and confirm what is included for the first upgrade. The main cost drivers are the number of business rules, how deeply the module inherits core Odoo models, and how many reviewers must sign off. Your own internal time also counts: staff who define requirements, test and approve are a real cost even when they are not billed by a partner.

How long does it take to build a custom Odoo module?

Duration depends mainly on how well the requirements are defined and how many parts of the core application the module touches. A small module that adds a few fields and a report can move quickly, while a module that changes sales approval, inventory valuation or accounting posting needs longer design and more regression testing. Ask a partner to show the phases in its quote: requirements sign-off, build, internal test, user acceptance test, and deployment. Clarify who is responsible for delays caused by late decisions or slow reviewer feedback, because those often extend the schedule more than the coding does. Request a duration only as a range tied to a defined scope, and confirm what changes the timeline, such as new integrations or additional user roles.

Can our in-house team build Odoo custom modules themselves?

Yes, if your team has working Python skills, experience with the Odoo framework (models, the ORM, XML views, access rights and record rules) and time to keep up with new major versions. Many teams start with a small internal project to learn the framework before taking on core-changing work. The risk is not the first module but the long tail: inheritance of core models that breaks after an upgrade, security rules that leak data between companies, and undocumented code that only one developer understands. Before deciding, check who will review code, who will write automated tests, and who will port the module at each upgrade. If those roles cannot be filled internally, a partner can cover part of the work under a fixed scope while your staff take over maintenance.

What do you need from our team before a custom module build starts?

A partner needs clear requirements, real or representative sample data, access to a test environment and named reviewers who can approve decisions. Requirements should describe the business process, the users and roles involved, the records created or changed, the approval steps and the reports expected. Sample data should cover typical cases and edge cases, such as partial shipments, multiple currencies or companies, so the tests reflect your operations. Access to a test database on your infrastructure or the agreed hosting is needed early, along with a process for sharing credentials securely. Reviewers should be available for scheduled walkthroughs and sign-off. Confirm these responsibilities in the written scope, because missing inputs are a common reason for rework and timeline slippage.

Which Odoo edition and plan allow custom modules on-premise or on Odoo.sh?

According to Odoo's pricing page, only the Custom plan can be hosted on Odoo.sh or on-premise, and only the Custom plan includes custom modules. The One App Free and Standard plans are offered on Odoo Online only, so they do not support custom module deployment on your own infrastructure. Custom modules can be developed for the Community edition, but the Enterprise edition is required for the upgrade service and for the Enterprise features many organizations rely on. Confirm the current plan terms with Odoo before purchase, since plan contents and prices change. Ask your partner to state which edition and plan the quote assumes, and whether the licensing cost is included or billed separately by you.

What does porting a custom module cost at each Odoo upgrade?

Porting cost is the effort to adapt a custom module to the new major version, including changes to APIs, views, and core models it inherits, followed by regression testing. Odoo major versions are released roughly yearly, and on Odoo Online and Odoo.sh major upgrades are mandatory every two years, so the work recurs for as long as the module is used. Standard support covers the first three years after a major release. The porting effort grows with the number of inherited core methods, the number of custom views and the amount of test coverage. Ask a partner to quote porting as a separate line item, state whether it is fixed or estimated per module, and explain how it is affected by staying within the standard support window.

How do we keep custom modules from breaking when Odoo is upgraded?

Keep the custom code small, inherit core models through documented extension points instead of copying them, and avoid changing core behavior that Odoo may rewrite. Automated tests for the module's business rules help show what broke after each upgrade. Test every upgrade on a copy of production data before go-live, using the upgraded test database, and record the results. Maintain a list of each custom module, its dependencies and its owner, and review third-party modules during the same cycle. Ask your partner whether the delivery includes tests, documentation of inherited methods and a porting checklist. These items reduce upgrade effort more than any single coding choice.

How DeployOpen scopes, builds and hands over Odoo modules

DeployOpen plans, implements, tests, documents and supports Odoo custom modules inside your own infrastructure, whether that is your cloud accounts, data centers or air-gapped networks. Engagements are fixed-scope, with the scope, deliverables and timelines agreed in writing before any build work starts.

How we scope

  • We confirm which business requirement cannot be met by configuration or existing apps before any module is designed.
  • The written scope lists each model, view, security rule, inherited core module and test suite the module will include.
  • We record the Odoo version, edition and hosting target, since these determine what custom code is permitted and how it will be upgraded.

How we build

  • Modules are written in Python with models, views and access rules defined in the module, following the Odoo module structure for the agreed version.
  • Core modules are extended through inheritance rather than copied, so upstream changes remain visible and easier to port later.
  • Each module ships with automated tests and a code review before it is merged into the environment where it will run.

How we hand over

  • Handover includes source code in your repository, installation steps and a record of the dependencies each module needs.
  • Technical documentation describes models, extension points, security groups and known limits so your team can maintain the code.
  • We test the module on a duplicated database copy with neutralization before it is applied to production data.

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer after go-live.
  • Each major Odoo version upgrade includes porting the custom modules and testing them on an upgraded test database first.
  • Confirm with us in the quote how porting effort at each version change is priced, since it depends on how much core code each module touches.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.