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.dependsvs formula fields. - You need ORM inheritance (
_inherit) or model delegation.
Feature Comparison Table
| Feature | Studio | Custom Module |
|---|---|---|
| Add fields to a model | Yes | Yes |
| Modify view layout | Yes | Yes |
| Create new model | Yes (limited) | Yes (full power) |
| Python business logic | No | Yes |
ORM constraints (@api.constrains) | No | Yes |
| Onchange handlers | No | Yes |
| Stored computed fields | No (formula = non-stored) | Yes |
| Custom JavaScript / OWL | No | Yes |
| Email & PDF reports | Yes (basic) | Yes (full QWeb) |
| Automated actions | Yes | Yes |
| Version control (git) | No (DB-stored) | Yes |
| Deploy to multiple instances | Manual export/import | Install module |
| Odoo Community compatible | No | Yes |
| Requires developer skill | No | Yes |
| Time to first working change | Minutes | Hours to days |
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:
- In Studio, click the Export button in the top toolbar.
- Download the ZIP file.
- Unzip it — you'll find a standard module structure:
__manifest__.py,models/,views/,security/,data/. - Add the module to your Odoo addons path.
- From this point, manage the module in git and add Python logic as needed.
- Disable or uninstall the Studio customizations from the database to avoid conflicts.
The exported module looks like this:
{
'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,
}
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:
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
| Scenario | Recommended approach |
|---|---|
| Quick field addition, Enterprise, no logic | Studio only |
| Prototyping a new app for client review | Studio first, export to module later |
| Multi-instance deployment, version control required | Custom module from the start |
| Community edition customer | Custom module only |
| Add validation to existing Studio field | Custom module that references Studio field |
| Complex workflow with approvals, API calls | Custom module only |
| Rebranding a form view for a specific team | Studio (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
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.
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.
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.
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.