# WooCommerce scheduled sale not working? Every cause and the fix

Source: https://salesdrawer.com/blog/woocommerce-scheduled-sale-not-working/ · Published 2026-10-07 · By Sale Drawer team · Category: WooCommerce how-to

> Your WooCommerce scheduled sale didn't start, didn't end, or shows on the product page but not in the shop. Here is why it happens and how to fix each cause.

A WooCommerce scheduled sale that "isn't working" almost always comes down to one of six causes: the daily scheduled action that switches prices hasn't run, the store timezone is wrong, the schedule was set on the parent product instead of its variations, a page cache is serving the old price, the sale price was saved in a way WooCommerce rejects, or the product lookup table is stale. This guide walks through each one in the order you should check them, with the exact screen to look at.

If you haven't set up the sale yet, start with [how to schedule a sale in WooCommerce](/blog/how-to-schedule-a-sale-in-woocommerce/). If it's set up and misbehaving, read on.

## How WooCommerce actually switches a scheduled sale

Understanding the mechanism explains most of the symptoms.

When you save a product with a sale price and a date range, WooCommerce stores three things: the regular price, the sale price, and the *active* price (the `_price` value that the shop grid, price sorting, price filters and "on sale" queries use). The product page itself checks the sale dates live every time it loads, so it can show the sale the moment the start date arrives.

The stored active price, however, is only updated by a scheduled action called `woocommerce_scheduled_sales`, which WooCommerce runs **once a day, at midnight in your store's timezone**, through its [Action Scheduler](https://actionscheduler.org/) library. That action also refreshes the product lookup table that powers "on sale" queries.

So there are really two switches: a live one on the product page, and a once-a-day one for everything else. When they disagree, you get the classic complaint on the [WooCommerce support forums](https://wordpress.org/support/topic/woocommerce-schedule-sale-price-not-working/): the sale shows on the product page but not in the shop, or the old price lingers in a category grid after the sale has ended.

## Cause 1: the scheduled action hasn't run

**Symptom:** the sale started (or ended) on the product page, but the shop, sorting, filters and any "on sale" listing still show the old state. Or nothing changed at all on a low-traffic site.

**Why:** Action Scheduler is driven by WP-Cron, and WP-Cron only runs when someone visits the site. On a quiet store, or on a host that blocks the loopback request WP-Cron depends on, the midnight action can run hours late or not at all.

**Check it:** go to **WooCommerce → Status → Scheduled Actions**, search for `woocommerce_scheduled_sales` and look at the **Pending** and **Past-due** tabs. A past-due entry means the action is waiting for cron that never came.

**Fix it now:** hover the pending action and click **Run**. Prices update immediately.

**Fix it permanently:** replace WP-Cron with a real server cron so the action runs on time whether or not anyone visits. Add this to `wp-config.php`:

```php
define( 'DISABLE_WP_CRON', true );
```

Then add a system cron entry on your server (every five minutes is plenty):

```
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
```

If you have WP-CLI, `wp cron event run --due-now` does the same job. The WordPress developer handbook has the full write-up on [hooking WP-Cron into the system task scheduler](https://developer.wordpress.org/plugins/cron/hooking-wp-cron-into-the-system-task-scheduler/). Many managed hosts already do this for you; check your host's documentation before adding your own.

## Cause 2: the store timezone is wrong

**Symptom:** the sale starts or ends hours early or late, every time.

**Why:** sale dates are interpreted in the timezone set under **Settings → General → Timezone**. A "From" date starts at 00:00:00 and a "To" date ends at 23:59:59 in *that* timezone. If the setting still reads UTC+0 but your customers are in Chicago, your Friday sale begins on Thursday evening for them.

**Fix:** choose a **city** (for example "New York") rather than a numeric offset, so daylight saving time is handled automatically. Then re-save any products whose schedule was created under the old setting.

## Cause 3: the schedule is on the wrong product type

**Symptom:** a variable product shows no sale, or only some variations are discounted.

**Why:** for variable products, prices and schedules live on each **variation**, not on the parent. Setting a sale price on the parent's General tab does nothing visible.

**Fix:** edit the product, open the **Variations** tab, expand each variation and set its sale price and schedule. To do them all at once, use the **Bulk actions** dropdown above the variations: *Set sale prices*, then *Set scheduled sale dates*. There is a long-running [WooCommerce GitHub issue](https://github.com/woocommerce/woocommerce/issues/41710) documenting how scheduled sales on variable products can behave differently from simple ones, which is one more reason to check each variation after the sale starts.

## Cause 4: a page cache is serving yesterday's price

**Symptom:** you see the sale when logged in, but customers (or an incognito window) still see the old price.

**Why:** full-page caches such as WP Rocket, LiteSpeed Cache, WP Super Cache, Cloudflare APO and most host-level caches store a finished copy of each page. Logged-in admins bypass the cache, so you see fresh prices while everyone else sees the stale copy.

**Fix:** purge the cache the moment a sale starts and again when it ends. For sales that start at midnight, either schedule a purge or set the cache lifespan to an hour or less around the switch. We cover this in detail in [why your store still shows old sale prices](/blog/woocommerce-cache-old-sale-prices/). Anything you add to promote the sale should also be cache-aware; see the note on [deferred mode](/docs/getting-started/#behind-a-cache) in the Sale Drawer docs.

## Cause 5: the sale price was never accepted

**Symptom:** the schedule looks right but the product never goes on sale.

**Why:** WooCommerce silently drops a sale price that isn't lower than the regular price, or that uses the wrong decimal separator for your store's settings (typing `19,99` in a store configured for `.`). A sale price with no regular price is also ignored.

**Fix:** open the product, confirm the regular price is set and the sale price is lower and uses your store's decimal separator, then **Update**. If the "From" date is already in the past and the "To" date is in the future, the sale applies as soon as you save.

## Cause 6: the lookup table is stale

**Symptom:** everything is correct on the product page and the scheduled action has run, but "on sale" blocks, shortcodes and filters still miss the product.

**Why:** WooCommerce keeps a lookup table of prices and on-sale flags for fast queries. After a plugin conflict, a failed import or a bulk edit, it can fall out of sync with the products.

**Fix:** go to **WooCommerce → Status → Tools** and run **Regenerate the product lookup tables**, then **Clear transients**. Both are safe on a live store.

## A five-minute checklist when a sale misbehaves

1. **Scheduled Actions:** is `woocommerce_scheduled_sales` pending or past-due? Run it.
2. **Timezone:** is a city selected under Settings → General?
3. **Variations:** does each variation have its own sale price and dates?
4. **Cache:** does an incognito window show the same price you see logged in? If not, purge.
5. **Prices:** is the sale price lower than the regular price, in the right format?
6. **Lookup tables:** regenerate them if "on sale" queries still disagree with the product page.

## After the fix: make sure people see the sale

Once prices switch on time, the second half of the job is visibility. Most shoppers land on a product page or a blog post, not on your sale category, so a perfectly scheduled discount can run quietly for a week. [Why shoppers miss your WooCommerce sale](/blog/why-shoppers-miss-your-woocommerce-sale/) covers the usual leaks, and [how to show sale products on every page](/blog/show-sale-products-on-every-page-woocommerce/) walks through the fixes, from shortcodes to a site-wide drawer.

## Frequently asked questions

### Why does my scheduled sale show on the product page but not in the shop?

The product page checks sale dates live, while the shop grid, sorting and "on sale" listings use a stored price that is only updated by the daily `woocommerce_scheduled_sales` action. Run that action from WooCommerce → Status → Scheduled Actions, and set up a real server cron so it runs on time in future.

### Why is the sale price still showing after the end date?

Either the daily scheduled action hasn't run yet, so the stored price hasn't reverted, or a page cache is still serving the sale-period copy of the page. Run the action, then purge the cache.

### Does WP-Cron need to be running for scheduled sales?

Yes. WooCommerce uses Action Scheduler, which relies on WP-Cron unless you replace it with a system cron. On low-traffic sites, WP-Cron may not fire at midnight, which delays the price switch until the next visit.

### Do variations need their own sale schedule?

Yes. On a variable product, each variation has its own regular price, sale price and schedule. Use the bulk actions on the Variations tab to set them all at once.

### What time does a WooCommerce sale start and end?

A sale starts at 00:00:00 on the "From" date and ends at 23:59:59 on the "To" date, in the timezone set under Settings → General. The stored price used by the shop grid updates when the daily scheduled action runs, normally just after midnight.

### Can I make a scheduled sale start at a specific hour?

Not with the built-in schedule, which works in whole days. Tools that run promotions as campaigns, such as [Sale Drawer Pro](/docs/pro-features/#campaigns-and-priority), can start and end a promotion at an exact time, but the WooCommerce price itself still follows the daily schedule.
