719-286-0751 [email protected]

Magento 2 – Stuck or Long-Running Cron After Upgrade to 2.3.x

Magento 2 – Stuck or Long-Running Cron After Upgrade To 2.3.x

You may have recently upgraded your Magento 2 instance to 2.3.x, only to discover one of the below:

  • One or more index is no longer updating (if set to SAVE ON SCHEDULE)
  • One or more cron tasks does not seem to be happening
  • The entries in cron_schedule show no recently scheduled jobs

So, you check the system.log, the exception.log, and the cron log, finding nothing. If you look for the cron process:


ps aux | grep -i cron

You see output indicating a cron job has been running for some time — and the last timestamp matches up with the time of the last job in cron_schedule

What is going on??

The Problem(s)

There are multiple possible causes for this issue. Our article attempts to address two of the possible causes:

  1. Your instance is running message consumers through cron, without the proper settings in env.php
  2. Your instance has a large catalog, and is still using FLAT PRODUCTS or FLAT CATEGORIES

Verify Proper Message Consumer Settings

Magento 2.3.x introduces the message queue system: https://devdocs.magento.com/guides/v2.3/extension-dev-guide/message-queues/message-queues.html

These are a new way of running async processes. Magento actually recommends running them via RabbitMQ, but by default they are run through the cron process, using the database as the queuing mechanism.

According to Magento’s documentation as of today (found here:  https://devdocs.magento.com/guides/v2.3/config-guide/mq/manage-message-queues.html) the queue consumers are supposed to boot up every minute and do the following:

  1. Look for new queue messages in the database, reading up to –max-messages (by default 10,000)
  2. Shut down once all messages are processed, and move to the next cron job

The documentation even says:

–consumers-wait-for-messages : Specifies whether consumers should continue polling for messages if the number of processed messages is less than the max-messages value. The default value of 0 prevents stuck deployments caused by long delays in message queue processing. Set the value to 1 to allow consumers to wait for messages.

However, if you look in the code at this file: vendor/magento/framework-message-queue/CallbackInvoker.php – you will see the below:


    /**
     * Run short running process
     *
     * @param QueueInterface $queue
     * @param int $maxNumberOfMessages
     * @param \Closure $callback
     * @return void
     */
    public function invoke(QueueInterface $queue, $maxNumberOfMessages, $callback)
    {
        $this->poisonPillVersion = $this->poisonPillRead->getLatestVersion();
        for ($i = $maxNumberOfMessages; $i > 0; $i--) {
            do {
                $message = $queue->dequeue();
                // phpcs:ignore Magento2.Functions.DiscouragedFunction
            } while ($message === null && $this->isWaitingNextMessage() && (sleep(1) === 0));

            if ($message === null) {
                break;
            }

            if (false === $this->poisonPillCompare->isLatestVersion($this->poisonPillVersion)) {
                $queue->reject($message);
                // phpcs:ignore Magento2.Security.LanguageConstruct.ExitUsage
                exit(0);
            }

            $callback($message);
        }
    }

    /**
     * Checks if consumers should wait for message from the queue
     *
     * @return bool
     */
    private function isWaitingNextMessage(): bool
    {
        return $this->deploymentConfig->get('queue/consumers_wait_for_messages', 1) === 1;
    }

Notice that final function isWaitingForNextMessage() — this determines whether the queue consumer exits after processing all available messages or continues waiting. Contrary to what the documentation indicates, this is set to 1 by default, not 0 

So, this will cause the consumers to run forever, preventing additional crons from running. This is easily fixed by adding the below to your env.php file:


    'queue' => [
        'consumers_wait_for_messages' => 0
    ],

This will prevent Magento 2 from letting the consumers wait indefinitely. After doing that, make sure to flush the cache.

Flat Catalog Indices

The flat category and flat product indices are no longer recommended. Magento’s own documentation notes this, and mentions possible performance degradation: https://docs.magento.com/m2/ce/user_guide/catalog/catalog-flat.html — basically, having these indices enabled can cause your cron process to get stuck, time out, or miss other important jobs!

However, you may have missed that update — flat catalog has been a best practice since the early days of Magento 1. However, these are easy to disable via the admin through Stores -> Configuration -> Catalog -> Frontend

Make sure to test this change on a development environment first!! Some extensions and themes may be expecting the flat catalog!!

Alan Barber is the Lead Web Developer at Cadence Labs and a Magento 2 Certified Professional Developer.

Need help with Magento 2?

We’ve had a lot of experience building websites in Magento 2. If you need help, head over to the Cadence Labs contact page, or email us at [email protected]

Submit a Comment

Your email address will not be published. Required fields are marked *

Install our webapp on your iPhone! Tap and then Add to homescreen.
Share This