Skip to content
intermediate Phase 65 · Cron System

Cron Groups — Configuration and Concurrent Runs

Configuring cron groups in Magento 2: default and custom groups, group configuration options, concurrent run management, and performance tuning

45m
1 problems
Topic Progress 0%

Default and Custom Cron Groups

Default Group

<group id="default">
    <job name="cleanup" instance="Vendor\Cron\Cleanup" method="execute">
        <schedule>0 2 * * *</schedule>
    </job>
</group>

The default group handles most cron jobs. All jobs without a specific group go here.

Custom Cron Groups

Create separate groups for heavy or independent jobs:

<group id="vendor_import">
    <job name="import_products" instance="Vendor\Cron\ImportProducts" method="execute">
        <schedule>*/15 * * * *</schedule>
    </job>
    <job name="import_orders" instance="Vendor\Cron\ImportOrders" method="execute">
        <schedule>*/30 * * * *</schedule>
    </job>
</group>

Why Custom Groups?

  1. Isolation — heavy jobs don't block lightweight jobs
  2. Independent scheduling — run at different frequencies
  3. Concurrent execution — run multiple jobs simultaneously
  4. Monitoring — track group-specific performance

Group Configuration

cron_groups.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/cron_groups.xsd">
    <group id="vendor_import">
        <schedule_generate_every>15</schedule_generate_every>
        <schedule_ahead_for>20</schedule_ahead_for>
        <schedule_lifetime>15</schedule_lifetime>
        <history_cleanup_every>10</history_cleanup_every>
        <history_success_lifetime>60</history_success_lifetime>
        <history_failure_lifetime>480</history_failure_lifetime>
        <use_group>
            <group>default</group>
        </use_group>
    </group>
</config>

Configuration Options

Option Description Default
schedule_generate_every Minutes between schedule generation 15
schedule_ahead_for How far ahead to generate schedules (min) 20
schedule_lifetime How long a schedule stays valid (min) 15
history_cleanup_every Minutes between history cleanup 10
history_success_lifetime Minutes to keep success history 60
history_failure_lifetime Minutes to keep failure history 480

use_group

The use_group option allows a group to inherit jobs from another group:

<group id="vendor_heavy">
    <use_group>
        <group>default</group>
    </use_group>
</group>

This group runs all default jobs plus its own.

Concurrent Cron Runs

Running Groups Separately

# Run default group
php bin/magento cron:run --group default

# Run custom group
php bin/magento cron:run --group vendor_import

Cron Runners in Production

Set up separate cron runners for different groups:

# /etc/crontab — production setup
* * * * * php /var/www/html/bin/magento cron:run --group default
* * * * * php /var/www/html/bin/magento cron:run --group vendor_import
*/5 * * * * php /var/www/html/bin/magento cron:run --group index

Concurrency Control

Magento prevents concurrent execution of the same job:

-- Check for running jobs
SELECT * FROM cron_schedule
WHERE status = 'running'
AND job_code = 'vendor_product_sync';

If a job is already running, the scheduler skips it for that cycle.

Lock Files

Cron uses lock files to prevent duplicate runs:

var/cache/magento/cron/lock/
# Check locks
ls -la var/cache/magento/cron/lock/

# Remove stale locks
rm var/cache/magento/cron/lock/*

Performance Tuning

For high-traffic stores:

<!-- Reduce schedule generation interval -->
<schedule_generate_every>5</schedule_generate_every>

<!-- Extend schedule validity -->
<schedule_lifetime>30</schedule_lifetime>

<!-- Clean up history more frequently -->
<history_cleanup_every>5</history_cleanup_every>

Cron Group Best Practices

Group Organization

default — lightweight, frequent jobs (cleanup, email)
index — reindexing jobs
import — data import jobs (heavy, less frequent)
custom — module-specific heavy jobs

Monitoring Group Performance

-- Performance by group
SELECT
    job_code,
    COUNT(*) as total_runs,
    AVG(TIMESTAMPDIFF(SECOND, executed_at, finished_at)) as avg_duration,
    SUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) as errors
FROM cron_schedule
WHERE executed_at > DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY job_code
ORDER BY avg_duration DESC;

Common Issues

Issue Cause Fix
Jobs running late Schedule generation too slow Reduce schedule_generate_every
Jobs skipped Previous run still executing Check for long-running jobs
Lock files not releasing Process crashed Clean var/cache/magento/cron/lock/
History table growing cleanup_every too high Reduce history_cleanup_every

Production Setup

# Crontab for production
* * * * * /usr/bin/php /var/www/html/bin/magento cron:run 2>&1 | tee -a /var/log/magento-cron.log

Use process managers (supervisord) for reliability.

Practice Problems

0 / 1 solved
Cron Job Conflict

A heavy import job blocks lightweight email jobs. How do you reorganize cron groups to solve this?

Quiz

1. What does schedule_generate_every control?

Question 1 options

2. What is the default schedule_generate_every value?

Question 2 options

3. How do you run a specific cron group?

Question 3 options

4. What prevents concurrent execution of the same cron job?

Question 4 options

Flashcards

Question

What is schedule_generate_every?

Answer

Minutes between schedule generation — how often new cron_schedule entries are created

Question

What is schedule_ahead_for?

Answer

How many minutes ahead schedules are generated (default 20)

Question

What is schedule_lifetime?

Answer

How long a schedule entry stays valid before being marked as missed (default 15 min)

Question

Where are cron lock files stored?

Answer

var/cache/magento/cron/lock/

Question

How to run a specific cron group?

Answer

php bin/magento cron:run --group groupname

Revision Notes

Key Takeaways

  • 1. Cron groups isolate jobs and allow independent scheduling
  • 2. cron_groups.xml configures schedule generation, lifetime, and cleanup
  • 3. Separate cron runners per group prevent heavy jobs from blocking lightweight ones
  • 4. Lock files prevent concurrent execution of the same job
  • 5. schedule_generate_every (default 15) controls how often schedules are created
  • 6. Monitor cron performance with SQL queries on cron_schedule

Interview Tips

  • Explain why cron groups exist and when to create custom groups
  • Discuss the schedule_generate_every and schedule_lifetime settings
  • Describe how to set up concurrent cron runners
  • Know how to debug lock file issues

Cheat Sheet

Cron Groups Cheat Sheet

cron_groups.xml options:
schedule_generate_every: 15 (default)
schedule_ahead_for: 20
schedule_lifetime: 15
history_cleanup_every: 10
history_success_lifetime: 60
history_failure_lifetime: 480

Run specific group:
php bin/magento cron:run --group default

Lock files:
var/cache/magento/cron/lock/

Best practice:

  • default: lightweight jobs
  • index: reindexing
  • import: heavy imports
  • Separate cron runners per group