Odoo cron job causes duplicate processing under multi-worker setup despite state checks and commits
22:53 01 Jan 2026

I am working on a production module in Odoo (16.x) where a scheduled action (ir.cron) processes records that must be handled exactly once.

This works correctly in a single-worker environment, but breaks under a multi-worker production setup.

from odoo import api, models, fields
import logging

_logger = logging.getLogger(__name__)

class PaymentSync(models.Model):
    _name = 'payment.sync'

    state = fields.Selection([
        ('pending', 'Pending'),
        ('processing', 'Processing'),
        ('done', 'Done'),
    ], default='pending')

    @api.model
    def cron_sync_payments(self):
        records = self.search([('state', '=', 'pending')], limit=50)

        for rec in records:
            try:
                rec.state = 'processing'
                self.env.cr.commit()

                # External API call (takes ~3–5 seconds)
                rec._sync_with_gateway()

                rec.state = 'done'
                self.env.cr.commit()

            except Exception as e:
                _logger.exception("Payment sync failed: %s", e)
                rec.state = 'pending'
                self.env.cr.commit()

    def _sync_with_gateway(self):
        # Simulated external call
        pass

This cron runs every minute and multiple Odoo workers are enabled.

Expected Behavior

Each record with state = 'pending' should be:

  • Picked by only one worker

  • Processed exactly once

  • Moved to done state after successful execution


Actual Behavior / Error

In production, I observe:

  • The same record being processed by multiple workers

  • Duplicate external API calls for the same record

  • Inconsistent final state (doneprocessingdone)

  • No errors raised in logs

Even with:

  • Explicit state transitions

  • Manual commits

  • Record limits

the issue still occurs under load.


What I Have Tried

  • Adding limit to the search

  • Forcing commits after state changes

  • Increasing cron interval

  • Ensuring only one ir.cron record exists

None of these fully prevent duplicate execution.


Question

How does Odoo handle record selection and execution for cron jobs under a multi-worker setup, and what is the correct locking or transaction-safe pattern to ensure that each record is processed exactly once, even when multiple workers execute the same scheduled action concurrently?

postgresql cron odoo odoo-16