Skip to Content

How Odoo's Database Neutralization Works

A Complete Guide

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​) with state='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 in ir.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:

  1. Getting a list of all installed modules
  2. Looking for a data/neutralize.sql​ file in each module
  3. 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:

  1. Navigate to the database manager
  2. Choose "Restore Database"
  3. Check the "Neutralize" checkbox
  4. 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

in Dev
Setting up SSH Access to WSL from External Machines