Cron Functionality
Understanding how to configure and run scheduled background tasks in Magento 2.
Cron System Overview
What is Cron?
Understanding Cron Systems
System Cron (UNIX/Linux/MacOS)
- Operating system feature
- Runs tasks on schedule
- Time-based job scheduler
- Configured via crontab
Example: Run a script every 5 minutes
*/5 * * * * /path/to/script.shMagento Cron
- Built on top of system cron
- Executes pub/cron.php
- Manages internal job scheduling
- Uses cron_scheduletable
Purpose: Background tasks without HTTP requests
How Magento Cron Works
The Cron Workflow
Step-by-Step Process:
- System Cron Triggers - OS cron runs pub/cron.php(orbin/magento cron:run)
- Magento Pulls Jobs - Queries cron_scheduletable for jobs due to run
- Executes PHP Classes - Runs the execute()method of each job
- Updates Status - Marks jobs as success, error, or missed in database
- Once per minute: * * * * *
- Once per 5 minutes: */5 * * * *
- Once per 15 minutes: */15 * * * *
Cron Entry Point
pub/cron.php
The main entry point for Magento cron. System cron should trigger this file.
System Crontab Example:
* * * * * php /var/www/html/pub/cron.php
# Or using bin/magento
* * * * * php /var/www/html/bin/magento cron:runCron Job Structure
Cron Class Location
Cron jobs are PHP classes typically located in the Cron folder of a module:
Example Structure:
app/code/Bonlineco/OrderExport/
├── Cron/
│   └── ExportOrders.php
├── etc/
│   └── crontab.xml
└── registration.phpExample Cron Class:
<?php
namespace Bonlineco\OrderExport\Cron;
class ExportOrders
{
    protected $logger;
    
    public function __construct(
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->logger = $logger;
    }
    
    public function execute()
    {
        $this->logger->info('Cron job started: Export Orders');
        
        // Your cron logic here
        // Export orders, send emails, cleanup, etc.
        
        $this->logger->info('Cron job finished: Export Orders');
        return $this;
    }
}- Must have execute()method
- No parameters in execute()
- Use dependency injection for dependencies
- Return $thisorvoid
Configuring Cron Jobs
crontab.xml Configuration
Add a crontab.xml file to your module to register cron jobs:
Location:
app/code/Bonlineco/OrderExport/etc/crontab.xmlBasic Configuration:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="default">
        <job name="bonlineco_export_orders" instance="Bonlineco\OrderExport\Cron\ExportOrders" method="execute">
            <schedule>*/5 * * * *</schedule>
        </job>
    </group>
</config>Configuration Elements:
- <group id="default">- Cron group (default, index, etc.)
- name- Unique job identifier
- instance- PHP class to execute
- method- Method to call (usually "execute")
- <schedule>- Cron expression (when to run)
Cron Schedule Expression
Understanding Cron Syntax
Cron expressions consist of 5 fields:
* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of week (0-7, 0 and 7 are Sunday)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)Common Examples:
| Expression | Description | 
|---|---|
| * * * * * | Every minute | 
| */5 * * * * | Every 5 minutes | 
| 0 * * * * | Every hour (at minute 0) | 
| 0 0 * * * | Daily at midnight | 
| 0 2 * * * | Daily at 2:00 AM | 
| 0 0 * * 0 | Weekly on Sunday at midnight | 
| 0 0 1 * * | Monthly on the 1st at midnight | 
Cron Groups
Organizing Cron Jobs
Magento uses cron groups to organize and control job execution:
Default Cron Groups:
- default - General purpose cron jobs
- index - Indexing operations
- consumers - Message queue consumers
Configuring Group Settings:
Admin Path: Stores → Configuration → Advanced → System → Cron
Group Configuration Options:
- Generate Schedules Every - How often to generate new schedules
- Schedule Ahead For - How far ahead to schedule jobs
- Missed If Not Run Within - When to mark job as missed
- History Cleanup Every - How often to clean old records
- Success History Lifetime - How long to keep successful jobs
- Failure History Lifetime - How long to keep failed jobs
Cron Area Considerations
Important Area Context
Critical Issue:
All cron jobs execute in the crontab area by default, not frontend or adminhtml.
Problems this causes:
- Observers registered for frontend/adminhtml won't fire
- Area-specific configuration may not load
- Plugins may not work as expected
- Layout XML won't be processed
Solutions:
- Design cron jobs to be area-independent
- Manually set area if needed: $this->state->setAreaCode('frontend')
- Don't rely on frontend/adminhtml observers in cron
- Use global scope observers when possible
Testing and Debugging Cron
Testing Strategies
Method 1: Manual Cron Execution
php bin/magento cron:runRuns all due cron jobs immediately.
Method 2: Run Specific Group
php bin/magento cron:run --group=defaultMethod 3: Create Console Command (Recommended)
Why? Makes testing and debugging much easier!
Step 1: Create console command
app/code/Bonlineco/OrderExport/Console/Command/CronRun.php<?php
namespace Bonlineco\OrderExport\Console\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Bonlineco\OrderExport\Cron\ExportOrders;
class CronRun extends Command
{
    protected $exportOrders;
    
    public function __construct(
        ExportOrders $exportOrders,
        string $name = null
    ) {
        $this->exportOrders = $exportOrders;
        parent::__construct($name);
    }
    
    protected function configure()
    {
        $this->setName('bonlineco:cron:export-orders')
             ->setDescription('Run order export cron job manually');
    }
    
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('Starting order export...');
        $this->exportOrders->execute();
        $output->writeln('Order export completed!');
        return 0;
    }
}Step 2: Register in di.xml
<type name="Magento\Framework\Console\CommandList">
    <arguments>
        <argument name="commands" xsi:type="array">
            <item name="bonlineco_cron_export" xsi:type="object">
                Bonlineco\OrderExport\Console\Command\CronRun
            </item>
        </argument>
    </arguments>
</type>Step 3: Run command
php bin/magento bonlineco:cron:export-ordersMethod 4: PHPStorm Debugging
- Configure PHPStorm to run PHP Script
- Point to your console command
- Set breakpoints in cron class
- Debug with full IDE support!
Checking Cron Status
Using cron_schedule Table
Magento tracks all cron jobs in the cron_schedule table:
Query Recent Cron Jobs:
SELECT 
    job_code, 
    status, 
    scheduled_at, 
    executed_at, 
    finished_at,
    messages
FROM cron_schedule
WHERE job_code = 'bonlineco_export_orders'
ORDER BY scheduled_at DESC
LIMIT 10;Status Values:
- pending - Scheduled but not yet run
- running - Currently executing
- success - Completed successfully
- error - Failed with error
- missed - Didn't run within expected time
CLI Command:
php bin/magento cron:listShows all registered cron jobs and their schedules.
Best Practices
Do's
- Keep cron jobs fast and efficient
- Use logging for debugging
- Handle exceptions gracefully
- Create console commands for testing
- Use appropriate cron groups
- Set realistic schedules
- Monitor cron_scheduletable
- Clean up old cron records
Don'ts
- Don't run heavy operations every minute
- Don't rely on frontend/adminhtml area
- Don't forget error handling
- Don't assume system cron frequency
- Don't create long-running jobs (use queues instead)
- Don't skip logging
- Don't test only in production
Common Issues and Solutions
Troubleshooting
| Issue | Cause | Solution | 
|---|---|---|
| Cron not running | System cron not configured | Add cron entry to system crontab | 
| Jobs always "missed" | System cron runs too infrequently | Increase system cron frequency or adjust job schedule | 
| Observer not firing | Wrong area (crontab vs frontend) | Use global observers or set area manually | 
| Job runs too often | Schedule expression incorrect | Verify cron expression with crontab.guru | 
| Job appears twice | Duplicate configuration | Check for duplicate entries in crontab.xml | 
Exam Tips
Key Points to Remember
- Entry point: pub/cron.phporbin/magento cron:run
- Configuration file: etc/crontab.xml
- Cron class location: Cron/folder in module
- Required method: execute()with no parameters
- Cron expression format: 5 fields (minute, hour, day, month, weekday)
- Default area: crontab (not frontend or adminhtml)
- Status tracking: cron_scheduledatabase table
- Common groups: default, index, consumers
- Frequency limit: System cron frequency determines maximum job frequency
- Testing tip: Create console command wrapper for easier debugging
- Configuration: Stores → Configuration → Advanced → System → Cron
