Magento 2 Catalog Price Rules Not Applying? How Indexing Works
A catalog price rule is saved, active, the dates look right, and the storefront still shows the old price. This is one of the most frequent Magento support questions, and the answer is almost always in how catalog rules are indexed. This article explains the indexing chain in Magento Open Source and Adobe Commerce 2.4.8 and gives a debugging order that finds the cause quickly.
Catalog rules are precomputed
Cart price rules are evaluated when the cart is calculated. Catalog price rules are not. Magento evaluates the conditions of each catalog rule ahead of time, computes the discounted price for each matching product, and stores the result in index tables. The storefront then reads the final price from the price index, which already includes the rule price.
The advantage is speed. Category pages do not evaluate rules for every product. The downside is that any change to a rule, a product or a date only shows after the right indexers run.
The indexers and tables involved
| Indexer | What it does |
|---|---|
catalogrule_rule | Rebuilds rule matches and prices when a rule changes |
catalogrule_product | Rebuilds rule matches and prices when a product changes |
catalog_product_price | Builds the final price index, taking rule prices into account |
The main tables are:
catalogrule_product, one row per rule, product, website and customer group that matched, with the action and dates.catalogrule_product_price, the computed rule price per product, website, customer group and date.catalogrule_group_website, which rules apply to which website and customer group.
The date column in catalogrule_product_price is the key detail. Magento does not store a rule price for a date range. It stores one row per day, and it only computes a small window of days around the current date: yesterday, today and tomorrow. That is enough for timezone differences between websites, and it keeps the table small.
The daily cron
Because only a short window of days is stored, something has to move the window forward every day. That is the catalogrule_apply_all cron job, defined in Magento_CatalogRule and scheduled once a day. It runs a full reindex of the catalog rules so that the next day's prices exist before they are needed.
If cron does not run, rules keep working for a day or two with the rows that are already there, and then rule prices disappear from the storefront. This is the classic "rules stopped working on their own" case. Check that cron runs and that the job succeeds:
SELECT job_code, status, scheduled_at, executed_at, finished_at, messages
FROM cron_schedule
WHERE job_code = 'catalogrule_apply_all'
ORDER BY scheduled_at DESC
LIMIT 10;
More on keeping cron healthy in the cron jobs guide.
Debugging a rule that does not apply
I go through these in order. Most cases stop at one of the first four.
- Rule status and scope. Active, assigned to the right website, and to the customer group you are testing with. Testing logged out means the NOT LOGGED IN group.
- Applied. After saving a rule the admin shows a message that some rules are not applied until you click Apply Rules. That button triggers the rule reindex. With indexers on schedule, saving marks the work and cron picks it up.
- Indexers.
bin/magento indexer:statusshould show all three as valid with no backlog. - Caches. Full page cache stores the old price until the product's cache tags are cleaned. A reindex normally does this. If Varnish is in front and pages still show old prices, check that purge requests reach it.
- Conditions. Attributes used in conditions must have Use for Promo Rule Conditions set to Yes. The condition must match the product type you look at. For configurables, the children are what carry the price, so conditions on attributes that only exist on the parent can miss.
- Dates and timezones. Rule dates are dates without time, interpreted in the website's timezone. A rule starting today in one timezone can still be tomorrow in another.
- Stop further processing and priority. With several rules on the same product, priority and the stop flag decide which ones apply.
Check the index directly
When the admin looks right and the storefront does not, look at the tables. First, did the rule match the product?
SELECT rule_id, website_id, customer_group_id, from_time, to_time, action_operator, action_amount
FROM catalogrule_product
WHERE product_id = 123;
Then, was a rule price computed for today?
SELECT rule_date, website_id, customer_group_id, rule_price
FROM catalogrule_product_price
WHERE product_id = 123
ORDER BY rule_date, website_id, customer_group_id;
If there are no rows in catalogrule_product, the conditions or scope do not match. If rows exist there but not in catalogrule_product_price for today, the rule index is stale. If both exist and the storefront is wrong, look at the price index and the cache.
On Adobe Commerce, use the product's entity_id here, not the staging row_id.
Reindex by hand
bin/magento indexer:reindex catalogrule_rule catalogrule_product catalog_product_price
bin/magento cache:clean full_page
On a large catalog with many rules this takes time. Run it outside peak hours, or let the scheduled indexers do it.
Adobe Commerce: rules and staging
In Adobe Commerce, catalog price rules are part of content staging. You do not set dates on the rule itself. You schedule updates in the staging dashboard, and each update has a start and end time. The rule table has a row_id per version. Staging updates are applied by cron, so a scheduled rule that does not start on time usually points to cron or to the staging apply job. This is an Adobe Commerce only behavior and does not exist in Magento Open Source.
Performance of catalog rule indexing
The size of the rule index grows with products matched, times websites, times customer groups, times the days stored. A store with many customer groups and broad rules can produce millions of rows per reindex. A few things keep it manageable:
- Delete rules that expired. Inactive rules are skipped, but old rules pile up and make the admin and the reindex harder to read.
- Assign rules only to the customer groups that need them. Every group added multiplies the rows.
- Keep conditions simple. Conditions on many attributes or on category membership across a large tree are slower to evaluate during indexing.
- Put the indexers on schedule. Product saves then do not trigger a rule reindex during the request. See indexer modes: save vs schedule.
- Use price indexer dimensions on stores with several websites and many groups, so price index tables stay smaller.
If you need logic that cannot be expressed as a precomputed price, for example a price that depends on the cart, use a cart price rule or a custom totals collector instead. Forcing that logic into catalog rules leads to prices that do not match what the cart charges. The cart side is covered in custom cart price rule conditions.
Special price versus catalog rule
A product's special price and a catalog rule can both apply. Magento uses the lowest of the regular price, the special price and the rule price as the final price. If a rule seems to "not work", check whether a lower special price on the product is hiding it. Also check tier prices, which take part in the same minimum.
FAQ
Why does my Magento catalog price rule not show on the frontend?
Usually the rule was not applied, the indexers are stale, cron is not running, or the cache still holds the old page. Check rule scope and customer group, then the index tables for the product.
Why do catalog rules stop working after a few days?
Rule prices are stored per day for a short window. The daily catalogrule_apply_all cron extends that window. If cron stops, the stored days run out and rule prices disappear.
Do I need to click Apply Rules every time?
After changing a rule, yes, or let scheduled indexers process the change through cron. Product changes are picked up by the catalogrule_product indexer.
Can catalog price rules use customer attributes?
No. Catalog rules are precomputed per website, customer group and day, so they can only vary by those. Use customer groups or cart price rules for customer specific pricing.
I am available for freelance Magento and Adobe Commerce work, including pricing and promotion problems. If you need help with this, get in touch.
Related articles
Magento 2 Configurable Products Performance: What to Fix
Why configurable products slow down Magento 2 pages, admin saves and indexers, and how to fix it: variation counts, swatches, price indexing and data modeling.
Magento 2 Cron Jobs: Setup, Custom Jobs and Troubleshooting
How Magento 2 cron really works: crontab setup, cron groups, writing custom jobs, the cron_schedule table, queue consumers and fixing jobs that never run.
Common Magento 2 Errors and How to Fix Them
Fixes for classic Magento 2 errors: Area code is not set, Class does not exist, Invalid Form Key, stuck indexers, Unable to unserialize value, static 404s.
Magento 2 Salable Quantity Wrong? How Reservations Work
Why Magento 2 salable quantity differs from quantity, how inventory reservations work, and how to find and fix inconsistencies with the built in CLI commands.