Ad – 728×90
🎨 Odoo Studio

Odoo Studio vs Custom Module – When to Use Which

Studio and custom modules are not competing tools — they are different points on a spectrum of customization depth. Studio is optimized for speed and low barrier to entry; a custom module is optimized for power, maintainability, and portability. Knowing when to use each (or both) is one of the most practical decisions you'll make as an Odoo implementer or developer.

⏱️ 20 min 🎯 Intermediate 📅 Updated 2026

The Core Trade-off

The fundamental tension is between speed and control:

  • Studio gets you from idea to working customization in minutes — no development environment, no deployment, no code review needed. But it can only do what the Studio UI exposes.
  • A custom module gives you the full power of Python, the Odoo ORM, JavaScript, XML, and CSS — but requires a development workflow: write code, test, deploy, install/upgrade the module.

The practical rule: start with Studio; graduate to a module when you hit a wall.

When to Use Studio

Studio is the right choice when:

  • You need to add a few fields to an existing model (e.g., adding "Internal Reference" to Contacts).
  • You want to rearrange or simplify a form view for end-user clarity.
  • You need a simple automation (send email on state change, set a field on creation).
  • You're building a lightweight data collection app with no complex business rules.
  • You're prototyping — validating a workflow with users before committing to code.
  • Your client has an Enterprise subscription and needs customizations delivered the same day.
  • The person making changes is a business analyst or consultant, not a developer.

When to Write a Custom Module

A custom module becomes necessary when:

  • You need Python business logic — calculations, validations, ORM constraints, wizards.
  • The customization must work on Odoo Community (Studio is Enterprise only).
  • You need version-controlled, CI/CD-compatible code deployed from git.
  • The same customization needs to be installed on multiple Odoo instances.
  • You need custom JavaScript widgets, OWL components, or client-side behavior.
  • You're building an integration with an external API (REST, SOAP, EDI).
  • Performance matters — stored computed fields with @api.depends vs formula fields.
  • You need ORM inheritance (_inherit) or model delegation.

Feature Comparison Table

FeatureStudioCustom Module
Add fields to a modelYesYes
Modify view layoutYesYes
Create new modelYes (limited)Yes (full power)
Python business logicNoYes
ORM constraints (@api.constrains)NoYes
Onchange handlersNoYes
Stored computed fieldsNo (formula = non-stored)Yes
Custom JavaScript / OWLNoYes
Email & PDF reportsYes (basic)Yes (full QWeb)
Automated actionsYesYes
Version control (git)No (DB-stored)Yes
Deploy to multiple instancesManual export/importInstall module
Odoo Community compatibleNoYes
Requires developer skillNoYes
Time to first working changeMinutesHours to days
Ad – 336×280

Migrating from Studio to Module

When your Studio customizations outgrow what Studio can do, you don't lose your work. Studio's Export button generates a ZIP file containing a complete Odoo module:

  1. In Studio, click the Export button in the top toolbar.
  2. Download the ZIP file.
  3. Unzip it — you'll find a standard module structure: __manifest__.py, models/, views/, security/, data/.
  4. Add the module to your Odoo addons path.
  5. From this point, manage the module in git and add Python logic as needed.
  6. Disable or uninstall the Studio customizations from the database to avoid conflicts.

The exported module looks like this:

Python (__manifest__.py)
{
    'name': 'studio_customization',
    'version': '19.0.1.0.0',
    'author': 'Odoo Studio',
    'depends': ['sale'],
    'data': [
        'security/ir.model.access.csv',
        'views/sale_order_views.xml',
        'data/ir_model_fields.xml',
    ],
    'installable': True,
    'auto_install': False,
}
⚠️
Don't run both simultaneously

After you export Studio customizations to a module and install that module, keep both active only temporarily. Running the same customizations from both Studio (database records) and a module (files) can cause duplicated fields or view conflicts. Progressively remove the Studio versions once the module is stable.

Can You Mix Both?

Yes. Studio and custom modules coexist peacefully as long as they don't define the same things twice. Common mixing patterns:

Module references Studio fields

If Studio created a custom field (x_studio_approval_note) on sale.order, a custom module can reference it in Python:

Python
class SaleOrder(models.Model):
    _inherit = 'sale.order'

    def action_confirm(self):
        # Access a Studio-created field by its technical name
        for order in self:
            if not order.x_studio_approval_note:
                raise UserError("Please add an approval note before confirming.")
        return super().action_confirm()

Studio extends a module's model

If your custom module created a model project.equipment, you can open Studio on that model and add extra fields or modify views without touching the module code. This is particularly useful for field additions that don't need Python logic.

Recommendation matrix

ScenarioRecommended approach
Quick field addition, Enterprise, no logicStudio only
Prototyping a new app for client reviewStudio first, export to module later
Multi-instance deployment, version control requiredCustom module from the start
Community edition customerCustom module only
Add validation to existing Studio fieldCustom module that references Studio field
Complex workflow with approvals, API callsCustom module only
Rebranding a form view for a specific teamStudio (fast, no code, easy to adjust)

📋 Key Points

  • Studio = speed and low barrier; Custom module = power and maintainability. The best choice depends on your constraints.
  • Use Studio for field additions, view tweaks, simple automations, and prototyping on Enterprise.
  • Use a custom module for Python logic, Community compatibility, version control, and multi-instance deployment.
  • Studio's Export button generates a ZIP module you can unzip, add to git, and extend with Python.
  • After exporting, avoid running the same customizations from both Studio and the module simultaneously.
  • Custom modules can reference Studio-created fields by their x_ technical name.
  • Studio can extend a custom module's models without touching module code — a useful hybrid pattern.

FAQ

If I export Studio to a module and install it, should I uninstall Studio? +

You should disable the specific Studio customization records that are now covered by your module, but you don't need to uninstall Studio itself. Studio is used for ongoing no-code work. To disable the overlap: in developer mode, go to Settings → Technical → Views and deactivate the studio customization views that are now in your module's XML. Do the same for Studio-created fields if they're now in your module's model definition.

Can I use Studio to quickly add a field and then make it a "proper" field in my module? +

Yes — this is a common workflow. Use Studio to validate that the field is needed and named correctly. Then add the field definition to your Python model with the same technical name (e.g., x_approval_note). Once the module is installed, Odoo will detect the field already exists in the database and skip recreating the column. Then delete the Studio field record to avoid duplication. Test this on staging first.

Is Studio included in all Odoo Enterprise plans? +

Studio is available as an add-on with Odoo Enterprise. Some Enterprise contracts include it by default; others require an additional subscription for Studio. Check your Odoo.com account or contact Odoo to confirm. On Odoo.sh, Studio must be activated per project as well.

Does the exported module from Studio follow Odoo best practices? +

Mostly yes — it generates correct __manifest__.py, XML data files, and CSV access rules. However, the generated code may not follow all best practices: field names keep the x_studio_ prefix (which you should rename for production), and there is no Python code to extend. Treat the export as a clean starting scaffold and refactor it before using in production.