Executive Summary
Is your Magento 2 indexer showing 'working' or 'invalid' indefinitely? This is the diagnostic process and fix for stuck indexers — without causing downtime on a live store.
Magento 2 Indexer Stuck: Diagnosis and Fix
If you have ever opened System → Index Management and found an indexer permanently showing Working or Invalid — hours or days after it should have finished — you are dealing with one of the most common and frustrating operational problems in Magento 2.
The symptoms are consistent:
- Catalogue changes are not appearing on the storefront
- Price updates are not going live
- Category page products are stale
- Running
bin/magento indexer:statusshowsworkingindefinitely - Running
bin/magento indexer:reindexeither hangs or exits silently
This post walks through why this happens, how to safely diagnose the root cause, and how to fix it without causing downtime on a live store.
Why Magento Indexers Get Stuck
Magento indexers work by processing a queue of changes tracked in changelog tables (for Update by Schedule mode) or by running a full reindex on demand. A stuck indexer means the process that was processing the queue either crashed, ran out of memory, or was killed — without properly releasing its lock.
The three most common root causes are:
- A previous reindex process was killed mid-run (server restart, OOM kill, deployment script)
- A cron job that triggers indexing died without cleanup
- A deadlock or memory exhaustion during a large reindex
The indexer records a started_at timestamp in the indexer_state table when it begins. If the process dies before it can write the finished_at value, Magento sees an in-progress run and refuses to start another one — forever.
Step 1: Confirm the Indexer Is Genuinely Stuck
First, check the current status:
bin/magento indexer:statusYou will see output like:
+----------------------+------------------+-----------+---------------------+---------------------+
| Title | Status | Update On | Schedule Status | Schedule Updated |
+----------------------+------------------+-----------+---------------------+---------------------+
| Product Price | Working | Schedule | running (0 backlog) | 2026-04-23 14:22:01 |
| Catalog Product Rule | Reindex required | Schedule | idle | 2026-04-23 14:22:01 |
+----------------------+------------------+-----------+---------------------+---------------------+If the Working status has not changed in more than 15–20 minutes, it is stuck.
Now check whether there is actually a live reindex process running:
ps aux | grep magentoIf you see an active indexer:reindex process — wait for it. If nothing is running, the process has died and left the lock behind.
Step 2: Check the Database Lock Directly
The indexer state is stored in the indexer_state table. Query it:
SELECT indexer_id, status, updated, hash_config
FROM indexer_state
WHERE status = 'working';If rows come back with a status of working but no live process is running, those are ghost locks that need clearing.
Also worth checking the mview_state table, which tracks the changelog view status:
SELECT view_id, mode, status, updated, version_id
FROM mview_state
WHERE status = 'working';Step 3: Check for OOM Kills and Crash Evidence
Before clearing the lock, understand why the indexer died. Check the system logs:
# Check for OOM kills
sudo dmesg | grep -i 'killed process'
# Check PHP-FPM logs
sudo tail -100 /var/log/php-fpm/error.log
# Check Magento exception log
tail -100 var/log/exception.log
# Check Magento system log
tail -100 var/log/system.logCommon things you will find:
Out of memory: Kill process— the server killed the PHP process during a large reindexMaximum execution time exceeded—max_execution_timeinphp.iniis too low for large cataloguesDeadlock found when trying to get lock— a database deadlock killed the transaction
Fix the root cause first
Do not just clear the lock and reindex without understanding why it failed. If you clear without fixing, it will fail again — possibly causing data inconsistencies on the storefront.
Step 4: Fix the Root Cause
If the cause is OOM (Out of Memory)
Increase PHP memory for CLI processes. This is separate from the webserver PHP configuration:
# Check current CLI memory limit
php -i | grep memory_limit
# Override for a single reindex run
php -d memory_limit=2G bin/magento indexer:reindexFor a permanent fix, update your php.ini or create a CLI-specific override:
; /etc/php/8.3/cli/conf.d/99-magento.ini
memory_limit = 2G
max_execution_time = 3600If the cause is max_execution_time
For CLI scripts, max_execution_time should be 0 (unlimited). Confirm:
php -r "echo ini_get('max_execution_time');"If this returns anything other than 0, override it in your CLI php.ini.
If the cause is a database deadlock
A deadlock usually means two processes were writing to the same tables simultaneously. Check whether you have overlapping cron jobs:
SELECT job_code, status, scheduled_at, executed_at, finished_at
FROM cron_schedule
WHERE status = 'running'
ORDER BY executed_at DESC
LIMIT 20;If you see multiple indexer_reindex_all_invalid jobs with running status and no finished_at, your cron schedule is overlapping. This usually means the cron run interval is too short for your catalogue size, or cron is misconfigured to run more frequently than intended.
Step 5: Clear the Stuck Lock
Once you have identified and addressed the root cause, clear the ghost lock from the database.
Take a database backup first
Always back up your database before manually modifying indexer state tables. On a large catalogue this is critical.
Reset the stuck indexer state:
-- Reset all stuck indexers
UPDATE indexer_state SET status = 'invalid' WHERE status = 'working';
-- Or reset a specific indexer only (safer)
UPDATE indexer_state SET status = 'invalid'
WHERE indexer_id = 'catalog_product_price'
AND status = 'working';Reset stuck mview states:
UPDATE mview_state SET status = 'idle' WHERE status = 'working';Step 6: Reindex Safely
After clearing the lock, reindex the affected indexers. Do not reindex everything at once on a live store with a large catalogue — it will hit the same memory and deadlock problems.
Reindex individual indexers instead:
# List all indexers
bin/magento indexer:status
# Reindex a single indexer
bin/magento indexer:reindex catalog_product_price
# Reindex multiple specific indexers
bin/magento indexer:reindex catalog_product_price catalogsearch_fulltextIf you need to reindex everything and your catalogue is large, run each indexer separately with a gap between them to reduce database pressure:
for indexer in catalog_category_product catalog_product_category catalog_product_price catalogsearch_fulltext; do
echo "Reindexing: $indexer"
php -d memory_limit=2G bin/magento indexer:reindex $indexer
echo "Done: $indexer"
sleep 5
doneStep 7: Verify and Flush Cache
After reindexing completes:
# Confirm all indexers are valid
bin/magento indexer:status
# Flush cache
bin/magento cache:flush
# Or flush specific cache types
bin/magento cache:clean full_page block_htmlPreventing It From Happening Again
Switch to Update by Schedule
If you are running indexers in Update on Save mode, every product or price change triggers a synchronous reindex during the admin save operation. This is slow and increases the risk of timeouts. Switch to Update by Schedule:
bin/magento indexer:set-mode scheduleThis queues changes in changelog tables and processes them via cron, which is much safer for catalogues with more than a few hundred products.
Clean the cron_schedule Table Regularly
The cron_schedule table accumulates rows over time and can slow cron execution significantly:
-- Check table size
SELECT COUNT(*) FROM cron_schedule;
-- Delete old completed/failed rows (safe to run during low traffic)
DELETE FROM cron_schedule
WHERE status IN ('success', 'missed', 'error')
AND scheduled_at < DATE_SUB(NOW(), INTERVAL 7 DAY);Monitor Indexer Status
Add indexer status to your monitoring. A simple cron-driven check that alerts when any indexer has been in working state for more than 30 minutes will catch this before it becomes a customer-facing issue.
The Indexer Reference
| Indexer ID | What It Does | Impact When Stuck |
|---|---|---|
catalog_category_product | Category → product assignments | Wrong products in categories |
catalog_product_category | Product → category assignments | Products missing from nav |
catalog_product_price | Product pricing | Stale prices on storefront |
catalog_product_attribute | Layered nav attributes | Filters broken |
catalogsearch_fulltext | Search index | Search returns no results |
catalogrule_rule | Catalogue price rules | Promotions not applying |
catalogrule_product | Catalogue price rule products | Promotion prices not showing |
customer_grid | Admin customer grid | Admin search broken |
design_config_grid | Design config | Admin design settings |
When to Call It
If you have followed all of the above and indexers are still failing repeatedly, the problem is usually one of three things:
- Catalogue data quality — corrupted or malformed product records that cause the indexer to fail mid-run. Run
bin/magento catalog:images:resizeand check for errors as a proxy. - Extension conflict — a third-party module is observing indexer events and throwing exceptions that kill the process silently. Check
var/log/exception.logcarefully during a reindex attempt. - Infrastructure limits — the server genuinely does not have enough RAM or MySQL buffer pool size for your catalogue. This requires a hosting review.
If your indexers are failing repeatedly and the above has not resolved it, it is worth a proper technical audit of your environment before the problem cascades into other operational issues.
For professional support, see our Magento support retainers or if releases and operations are breaking more broadly, Magento project rescue.
Need help with Magento?
Planning Magento for your small business or start-up?
We help brands choose the right platform, launch lean Magento builds, and scale without wasting budget.
Related services: Magento project rescue, Hyvä and performance optimisation, and marketplace operations.
Free 20-minute call · No hard sales, ever.
