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?
- Isolation — heavy jobs don't block lightweight jobs
- Independent scheduling — run at different frequencies
- Concurrent execution — run multiple jobs simultaneously
- 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
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?
2. What is the default schedule_generate_every value?
3. How do you run a specific cron group?
4. What prevents concurrent execution of the same cron job?
Flashcards
Question
What is schedule_generate_every?
Click to reveal answer
Answer
Minutes between schedule generation — how often new cron_schedule entries are created
Question
What is schedule_ahead_for?
Click to reveal answer
Answer
How many minutes ahead schedules are generated (default 20)
Question
What is schedule_lifetime?
Click to reveal answer
Answer
How long a schedule entry stays valid before being marked as missed (default 15 min)
Question
Where are cron lock files stored?
Click to reveal answer
Answer
var/cache/magento/cron/lock/
Question
How to run a specific cron group?
Click to reveal answer
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