Magento 2 cron jobs — waarom je shop 's nachts vastloopt
Terug naar blog

Magento 2 cron jobs — waarom je shop 's nachts vastloopt

AuthorRuthger Idema
8 april 20269 min leestijd

Om 03:00 loopt je Magento shop vast. Indexers hangen. E-mails worden niet verzonden. Orders blijven steken. De oorzaak is bijna altijd hetzelfde: overlappende cron jobs die om resources vechten.

Magento 2 cron jobs — waarom je shop 's nachts vastloopt

Om 03:47 loopt je Magento-installatie vast. Indexers hangen. Transactionele e-mails komen niet aan. Nieuwe orders worden niet verwerkt. De oorzaak is zelden een bug. Bijna altijd zijn het overlappende cron jobs die om dezelfde resources vechten.

Cron is de stille motor achter Magento. Het is ook de meest verwaarloosde component van een productieinstallatie.

Wat je leert in dit artikel

  • Hoe Magento's cron-architectuur werkt (default en custom group)
  • Waarom overlapping het meest voorkomende probleem is
  • Debugging-aanpak stap voor stap
  • Scheduling-configuratie en resource management
  • Monitoring zodat je weet wat er 's nachts gebeurt

De architectuur van Magento cron

Magento 2 gebruikt twee cron-processen die je als systeemcron moet inrichten: cron:run en cron:run --group default.

In de praktijk draai je minimaal dit in je crontab:

bash
# Magento cron — minimale configuratie
* * * * * www-data php /var/www/html/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule"
* * * * * www-data php /var/www/html/bin/magento cron:run --group index 2>&1 | grep -v "Ran jobs by schedule"

Magento beheert intern de schedule. De systeemcron triggert elke minuut. Magento bepaalt zelf welke jobs wanneer draaien op basis van de cron_schedule tabel.

De twee cron groups

Standaard kent Magento twee groepen: default en index. Extensies kunnen eigen groepen toevoegen.

xml
<!-- etc/crontab.xml in een module -->
<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="vendor_module_sync" instance="Vendor\Module\Cron\Sync" method="execute">
            <schedule>0 2 * * *</schedule>
        </job>
    </group>
</config>

De index groep is bedoeld voor zware indexeer-operaties. Zet je eigen zware cron-jobs in een aparte groep, anders concurreren ze met de standaard jobs.

Het overlapping-probleem

Dit is de meest voorkomende oorzaak van nachtelijke problemen.

Scenario: je hebt een import-cron die elk uur draait. De import duurt normaal 40 minuten. Op een drukke dag duurt de import 70 minuten. Het volgende cron-proces start al terwijl het eerste nog loopt. Beide processen claimen dezelfde database-resources. Alles vertraagt. De derde run start ook. De database loopt vast.

sql
-- Controleer hoeveel cron jobs tegelijk lopen
SELECT job_code, status, COUNT(*) as count
FROM cron_schedule
WHERE status = 'running'
GROUP BY job_code, status
ORDER BY count DESC;

Magento's ingebouwde bescherming

Magento heeft een max_running_jobs instelling per cron group:

xml
<!-- Configureer in app/etc/env.php of via admin -->
'cron_groups' => [
    'default' => [
        'schedule_generate_every' => 15,
        'schedule_ahead_for' => 20,
        'schedule_lifetime' => 15,
        'history_cleanup_every' => 10,
        'history_success_lifetime' => 10080,
        'history_failure_lifetime' => 10080,
        'use_separate_process' => 1,
        'max_running_jobs' => 3,
    ],
]
max_running_jobs voorkomt dat ongelimiteerd veel jobs tegelijk starten. Maar het lost het probleem van individuele jobs die langer duren dan verwacht niet op. Daarvoor heb je locking nodig.

Debugging stap voor stap

Stap 1: Bekijk de cron_schedule tabel

sql
-- Recente cron-geschiedenis
SELECT job_code, status, scheduled_at, executed_at, finished_at,
       TIMESTAMPDIFF(SECOND, executed_at, COALESCE(finished_at, NOW())) as duration_seconds,
       messages
FROM cron_schedule
WHERE scheduled_at > NOW() - INTERVAL 24 HOUR
ORDER BY scheduled_at DESC
LIMIT 100;

Zoek naar:

  • Jobs met status running die allang niet meer zouden moeten lopen
  • Jobs met status missed — die zijn nooit gestart
  • Jobs met extreem lange durations

Stap 2: Controleer op zombie-processen

bash
# Bekijk lopende PHP-processen
ps aux | grep "cron:run" | grep -v grep

# Bekijk hoeveel processen er zijn
ps aux | grep "cron:run" | grep -v grep | wc -l

Als je meer dan 5-10 cron-processen ziet, is er een probleem.

Stap 3: Check de logs

bash
# Magento cron log
tail -f /var/www/html/var/log/cron.log

# System log op fouten
tail -f /var/www/html/var/log/system.log | grep -i "cron\|error\|critical"

# PHP process monitor
grep "cron" /var/log/php-fpm/error.log | tail -50

Stap 4: Analyseer de database-load

sql
-- Welke queries lopen tijdens cron-piek
SHOW PROCESSLIST;

-- Slow queries gerelateerd aan cron
SELECT query_time, sql_text
FROM mysql.slow_log
WHERE sql_text LIKE '%cron%'
ORDER BY query_time DESC
LIMIT 20;

Resource management

Memory limits

Zware cron jobs — grote imports, herschrijven van URL-keys, massa-indexering — vergen veel geheugen.

bash
# PHP memory limit voor CLI processen
# In php.ini of via .htaccess
memory_limit = 2G

# Of per job controleren
php -d memory_limit=4G bin/magento cron:run --group index

Timeouts voorkomen

php
// Zware cron jobs: geef het geheugen terug per batch
public function execute(): void
{
    $collection = $this->productCollectionFactory->create();
    $collection->setPageSize(500);
    $lastPage = $collection->getLastPageNumber();

    for ($page = 1; $page <= $lastPage; $page++) {
        $collection->setCurPage($page)->load();

        foreach ($collection as $product) {
            $this->processProduct($product);
        }

        // Geef geheugen vrij na elke batch
        $collection->clear();
        gc_collect_cycles();
    }
}

Scheduling spreiding

Zet zware jobs niet allemaal op hetzelfde tijdstip. Een schedule waarbij drie grote imports tegelijk starten om 02:00 is een recept voor problemen.

xml
<!-- Goede spreiding: meerdere imports op verschillende tijden -->
<job name="import_products" ...>
    <schedule>0 1 * * *</schedule>  <!-- 01:00 -->
</job>
<job name="import_prices" ...>
    <schedule>0 2 * * *</schedule>  <!-- 02:00 -->
</job>
<job name="import_stock" ...>
    <schedule>30 2 * * *</schedule> <!-- 02:30 -->
</job>

Monitoring

Je wil niet 's ochtends merken dat de nachtelijke cron is vastgelopen. Je wil dat een alert je om 03:00 wakker maakt.

Minimale monitoring-setup:

bash
#!/bin/bash
# check-cron.sh — draai dit elke 15 minuten via systeemcron

ZOMBIE_THRESHOLD=10
RUNNING=$(ps aux | grep "cron:run" | grep -v grep | wc -l)

if [ "$RUNNING" -gt "$ZOMBIE_THRESHOLD" ]; then
    echo "ALARM: $RUNNING cron processen actief" | mail -s "Magento cron alarm" [email protected]
fi

# Check op stuck running jobs
STUCK=$(mysql -u magento -p"$DB_PASS" magento -e "
    SELECT COUNT(*) FROM cron_schedule
    WHERE status = 'running'
    AND executed_at < NOW() - INTERVAL 2 HOUR;" -s -N)

if [ "$STUCK" -gt "0" ]; then
    echo "ALARM: $STUCK cron jobs al 2+ uur in running status" | mail -s "Magento cron stuck" [email protected]
fi

Integreer dit in je bestaande monitoring — of gebruik een tool als Oh Dear of BetterUptime met HTTP checks op een health-endpoint dat de cron-status teruggeeft.

Veelgemaakte fouten

1. Cron niet inrichten op nieuwe servers

Na een servermigratie wordt de systeemcron vergeten. Alles werkt, tot de eerste keer dat een geplande job moet draaien.

2. Te agressieve schedule op zware jobs

Een import van 50.000 producten elk kwartier inplannen is geen goed idee. Plan zware jobs maximaal één keer per uur, bij voorkeur 's nachts.

3. cron_schedule tabel niet opruimen

De tabel groeit ongelimiteerd als je geen opschoning configureert. Na een jaar heeft de tabel miljoenen rijen en worden queries op die tabel langzaam.

sql
-- Handmatig opruimen van oude cron history
DELETE FROM cron_schedule
WHERE scheduled_at < NOW() - INTERVAL 7 DAY
AND status IN ('success', 'missed');
4. Foutmeldingen in cron-output negeren

Redirect cron-output naar een logbestand en bekijk dat regelmatig. Stille fouten in cron zijn de moeilijkst te debuggen problemen.

Conclusie

Magento cron is eenvoudig te onderschatten. De standaard configuratie werkt voor kleine installaties. Bij groei en meer extensies worden overlappende jobs, resource-uitputting en ontbrekende monitoring serieuze risico's.

Richt je cron-monitoring in voordat je een probleem hebt. Spreide zware jobs over de nacht. Controleer wekelijks de cron_schedule tabel op anomalieën.

Heb je aanhoudende cron-problemen op je Magento-installatie? Bekijk onze Magento diensten of neem contact op — wij kijken graag mee.


Meer over monitoring van je Magento-omgeving? Lees Magento 2 monitoring.
Ruthger Idema

Geschreven door Ruthger Idema

15+ jaar ervaring in e-commerce development. Gespecialiseerd in Magento, Shopify en Laravel maatwerk.

Meer over ons team →
Deel dit artikel:

Wil je jouw e-commerce naar het volgende niveau?

Plan een vrijblijvend gesprek met onze experts over Magento, Shopify of Laravel maatwerk.

Plan een Tech Check