Magento 2 Cron & Indexer Stuck? A Field Triage Checklist
Magento 2 cron and indexer triage is a diagnostic routine for store operators and developers that gets a stuck cron_schedule queue or an indexer frozen in processing moving again, fast, without a blind reindex.
Read cron_schedule in the DB and run bin/magento indexer:status before touching anything.
A wall of missed rows = the OS crontab that calls cron:run is dead or one long job blocks the group.
An index stuck on processing for hours = a stale lock (OOM-killed worker, dangling DB/Redis lock), not real work.
Know your modes: Update on Save vs Update by Schedule changes how a stuck index behaves.
Recovery order: reset the stuck index, clear the lock, fix the crontab, then reindex the ONE broken index.
Is cron actually running?
Magento schedules jobs into cron_schedule but relies on an OS crontab to call bin/magento cron:run every minute. If that is missing, jobs sit in pending then age out to missed.SELECT job_code, status, COUNT(*) c FROM cron_schedule GROUP BY job_code, status ORDER BY c DESC; crontab -l -u www-data | grep cron:run
Reinstall the schedule with Magento's own installer rather than hand-editing:bin/magento cron:install
What is the difference between Update on Save and Update by Schedule?
Update on Save recalculates the index the moment you save (slower saves, no cron dependency). Update by Schedule only writes a row into an MView changelog table that cron consumes later (fast saves, but a stale storefront if cron dies). Put catalog, price and stock on schedule.bin/magento indexer:show-mode bin/magento indexer:set-mode schedule catalog_product_price
Why is my indexer stuck on processing?
It is waiting on a lock no live process will release, usually an OOM-killed worker (exit 137), a dangling GET_LOCK() DB lock, or an orphaned Redis lock key. Reset, then reindex only that index:bin/magento indexer:reset catalog_product_price bin/magento indexer:reindex catalog_product_price
If the lock backend is Redis (lock.config in env.php) and reset does not free it, drop the orphaned key directly with redis-cli.
bin/magento indexer:status bin/magento indexer:reset catalog_product_price DELETE FROM cron_schedule WHERE status IN ('missed','error'); bin/magento indexer:reindex catalog_product_price bin/magento cache:flush
On memory-tight boxes a full reindex of all indexers is the thing that gets OOM-killed in the first place. Fix the single broken index, watch top, batch the rest only once you have headroom.
I keep this in my own runbook, longer cases live on my Magento engineering blog, and the "cron died after an upgrade" pattern is what my Magento upgrade service hardens against. I'm also Kishan on Magento Stack Exchange., Adobe-Certified Magento 2 + Hyvä developer, kishansavaliya.com.