What is Database Neutralization?
Database neutralization is Odoo's built-in safety feature that disables production-sensitive operations in a database, making it safe for testing, development, or sharing. When you neutralize a database, Odoo systematically disables features that could cause real-world consequences if accidentally triggered in a non-production environment.
Common use cases:
- Restoring production backups to staging/development environments
- Sharing database copies with developers or consultants
- Creating test databases from production data
- Setting up demo environments
What Gets Neutralized?
When you neutralize an Odoo database, the system disables several critical production features:
1. Email Servers
- Outgoing mail servers (
ir.mail_server
) are deactivated - A dummy mail server is inserted to prevent fallback to command-line configured servers
- Incoming mail servers (
fetchmail.server
) are deactivated - Email templates are disconnected from mail servers
2. Scheduled Actions (Crons)
- All scheduled actions (
ir.cron
) are deactivated - Exception: The autovacuum job remains active (essential for database health)
- Prevents automated tasks from running accidentally
3. Webhooks
- All server actions (
ir.act_server
) withstate='webhook'
have their URLs replaced with a dummy value - Prevents external systems from being triggered
4. Payment Providers
- Payment providers (
payment.provide
r) are set to'disabled'
state - Prevents real payment processing in test environments
- Includes legacy payment acquirers for older Odoo versions
5. Integration Services
- IAP (In-App Purchase) account tokens are suffixed with
'+disabled'
- Third-party integrations (EDI systems, delivery providers, etc.) are disabled via module-specific neutralization scripts
6. Neutralization Flag
- Sets
database.is_neutralized
parameter inir.config_parameter
- This flag prevents certain operations from re-enabling neutralized features
The Modular Neutralization System
Odoo's neutralization is modular and extensible. The core system works by:
- Getting a list of all installed modules
- Looking for a
data/neutralize.sql
file in each module - Executing all found SQL scripts in sequence
This means each Odoo module can define its own neutralization behavior!
Module-Specific Neutralization
Many modules include their own neutralization scripts. For example:
Payment Module (/odoo/addons/payment/data/neutralize.sql
):
UPDATE payment_provider SET state = 'disabled' WHERE state NOT IN ('test', 'disabled');
Mail Module (/odoo/addons/mail/data/neutralize.sql
):
-- Deactivate mail template servers UPDATE mail_template SET mail_server_id = NULL; -- Deactivate fetchmail servers UPDATE fetchmail_server SET active = false; -- Delete web push notification keys DELETE FROM ir_config_parameter WHERE key IN ('mail.web_push_vapid_private_key', 'mail.web_push_vapid_public_key');
How to Neutralize a Database
Method 1: Using the CLI (Odoo 16+)
The simplest method is using Odoo's built-in CLI command:
odoo-bin neutralize --config /path/to/odoo.conf -d database_name
Advantages:
- Official Odoo command
- Executes all module-specific neutralization scripts
- Automatically handles version-specific differences
Be sure to have neutralize
before --config
You must include the -d database_name
flag with nuetralize
Method 2: During Database Restore (Web UI)
When restoring a database through Odoo's web interface:
- Navigate to the database manager
- Choose "Restore Database"
- Check the "Neutralize" checkbox
- Upload your backup file
Odoo will automatically neutralize the database after restoration.
Method 3: Using Python API
You can call Odoo's neutralization function directly via Python:
import odoo from odoo.sql_db import db_connect # Connect to the database db = db_connect('database_name') with db.cursor() as cr: # Call Odoo's neutralization function odoo.modules.neutralize.neutralize_database(cr) cr.commit()
Advantages:
- Direct access to Odoo's internals
- Can be integrated into custom scripts
- Always uses Odoo's latest neutralization logic
How the Neutralization Flag Works
The database.is_neutralized
flag in ir.config_parameter
serves two purposes:
1. Marker Flag
It indicates that a database has been neutralized. You can check it programmatically:
is_neutralized = env['ir.config_parameter'].sudo().get_param('database.is_neutralized') if is_neutralized: # Database is neutralized pass
2. Prevention Mechanism
Odoo code checks this flag to prevent re-enabling neutralized features:
Example from ir.cron.toggle()
:
def toggle(self, model, domain): # Prevent deactivated cron jobs from being re-enabled on neutralized databases if self.env['ir.config_parameter'].sudo().get_param('database.is_neutralized'): return True # Pretend success, but don't actually enable active = bool(self.env[model].search_count(domain)) return self.try_write({'active': active})
Example from iap.account.create()
:
def create(self, vals_list): accounts = super().create(vals_list) if self.env['ir.config_parameter'].sudo().get_param('database.is_neutralized'): # Disable new IAP accounts on neutralized databases for account in accounts: account.account_token = f"{account.account_token.split('+')[0]}+disabled" return accounts
Verifying Neutralization
After neutralizing a database, verify that it worked:
-- Check neutralization flag SELECT value FROM ir_config_parameter WHERE key = 'database.is_neutralized'; -- Should return: true -- Check mail servers SELECT name, active FROM ir_mail_server; -- Should show: 'neutralization - disable emails' with active=true, others false -- Check active crons (should only be autovacuum) SELECT COUNT(*) FROM ir_cron WHERE active = true; -- Should return: 1 -- Check payment providers SELECT name, state FROM payment_provider; -- All should be: disabled -- Check webhooks SELECT name, webhook_url FROM ir_act_server WHERE state = 'webhook'; -- Should show: 'neutralization - disable webhook'
Best Practices
✅ DO:
- Always neutralize production backups when restoring to non-production environments
- Verify neutralization after restoring databases
- Use the CLI command when possible (most reliable)
- Test neutralization in a safe environment first
- Document your neutralization procedures
- Automate neutralization for CI/CD pipelines (with safety checks)
❌ DON'T:
- Never neutralize production databases (data loss risk)
- Don't skip neutralization when sharing databases containing real data
- Don't rely only on manual steps - automate when possible
- Don't forget module-specific neutralizations - use Odoo's built-in methods
- Don't assume neutralization is permanent - features could be re-enabled manually
Conclusion
Odoo's neutralization system is a powerful safety mechanism that makes it safe to work with production data in non-production environments. By understanding how it works and following best practices, you can:
- Safely restore production backups for testing
- Share databases without risking production consequences
- Automate testing environments with confidence
- Prevent accidental emails, payments, or external integrations
Remember: When in doubt, neutralize! It's always safer to disable production features in test environments than to risk real-world consequences.
Resources:
- Odoo Source Code:
/odoo/odoo/modules/neutralize.py
- Base Neutralization SQL:
/odoo/addons/base/data/neutralize.sql
- CLI Documentation:
odoo-bin neutralize --help