Last reviewed June 2026. Verified against PrestaShop 1.7, 8 and 9. PS9 note: the discount back office is being unified into four discount types (Catalog, Cart, Free-Shipping, Free-Gift) behind a feature flag, but every type still carries the date window this guide relies on.

It is 11 PM on Thursday and you remember that the Black Friday promotion was supposed to go live at midnight. You scramble to create cart rules and change prices, hoping you do not fat-finger a decimal under pressure. Or the quieter version of the same mistake: you set a "weekend only" discount on Friday, forget it on Monday, and hand away margin for three extra days before anyone notices. Both failures share one root cause. A human being is the on/off switch.

PrestaShop can be that switch instead. Both of the platform's discount mechanisms, cart rules and specific prices, carry their own start and end timestamps, and the store evaluates them on every page load. Set the dates once, and the promotion turns itself on and off whether or not you are awake. This guide is specifically about that scheduling layer: where the date fields live, how PrestaShop decides a discount is "active" at any given moment, the timezone trap that silently shifts your launch, and the content that has to be scheduled alongside the price. For the strategy of which discount type to reach for in the first place, see running a sale in PrestaShop; for when in the year to run them, the seasonal sales calendar.

How PrestaShop actually decides a discount is "live"

Discount campaign schedule tab with required start date and end date fields for a timed promotion
The schedule tab where a promotion is given an exact start and end date so it switches on and off automatically.

It helps to know what is happening under the hood, because it dictates everything that follows. PrestaShop does not run a scheduled job at midnight that flips your promotion on. There is no cron task, no queue. Instead, both cart rules and specific prices store a date_from and date_to in the database, and the price is recalculated at request time: when a customer loads a product page or refreshes the cart, the core compares those timestamps against now and includes the discount only if now falls inside the window.

So what does that mean for you? Three practical things. First, activation is instant and reliable. There is no job that can fail to fire, so a promotion set for 00:00 genuinely starts at 00:00. Second, "now" is evaluated by the shop/PHP runtime timezone configuration, not the visitor's local timezone (the timezone trap below). Third, because the price is computed live and then cached, a promotion that should have started may still show the old price until the page cache is rebuilt. Which is why aggressive full-page caching and scheduled discounts need to be reconciled, covered later.

Scheduling a cart rule (Catalog → Discounts)

Cart rules are PrestaShop's voucher engine, both the codes a customer types and the automatic discounts that apply silently when conditions are met. You create one at Catalog → Discounts → New cart rule (in PrestaShop 1.6 the path is Price Rules → Cart Rules). To schedule it, open the Conditions tab and set Valid from / Valid to:

  • Valid from, date and time the rule becomes usable. Stored as date_from.
  • Valid to, date and time it expires. Stored as date_to.

Inside that window the rule is live; outside it, the code is rejected with "this voucher is not valid" and an automatic rule simply does not apply. Two fields most merchants skip are worth setting deliberately:

  • Total available and Total available for each user, usage caps. A scheduled date range answers "when"; these answer "how many times," which is how you stop a leaked code from being abused for the full window.
  • Highlight and Partial use, on the Actions tab. Highlight nudges the customer toward an applicable voucher in the cart; partial use decides whether an unspent remainder of a fixed-amount voucher survives to the next order.

One thing the back office will not stop you doing: setting "Valid to" earlier than "Valid from." There is no guard rail, the rule just never activates, and you find out when a customer emails asking why EARLY20 does not work. Read the two dates back before you save.

The Valid from / Valid to pickers on a cart rule's Conditions tab, both carry a time, not just a date, and there's no guard rail against setting "to" before "from".

Scheduling a price drop on products (specific prices)

Cart rules discount the basket. To put a crossed-out price on the product page itself, the classic sale presentation, old price struck through, new price in red, you use a specific price, set per product under Catalog → Products → [your product] → Pricing → Specific prices → Add a specific price. The same dialog appears when you bulk-assign a catalogue price rule under Catalog → Discounts → Catalog price rules, which is how you schedule a discount across a whole category or supplier at once rather than product by product.

The dialog carries its own From and To date-time fields, the same from/to columns on the ps_specific_price table, plus controls that cart rules do not have:

  • For (customer group), restrict the scheduled price to a group, so "wholesale week, −20% for resellers" co-exists with normal retail pricing in the same window.
  • Available quantity / From quantity, tier the discount by units bought, scheduled to a date range.
  • Leave the dates blank, and the specific price is permanent. The date fields are what turn a standing price into a timed promotion; clearing them is how you make a sale price "stick" deliberately.

The visible difference for the shopper is the point of choosing one over the other: a specific price shows on the catalogue and product page before anything is added to the cart, so it advertises the deal; a cart rule typically reveals itself at the basket. If you are unsure which mechanism a given promotion wants, the cart rules vs specific prices breakdown is the decision framework.

Auditing your scheduled windows in one query

When you've staged a quarter of promotions in advance, it pays to read them all back in one place rather than clicking through each product. These are read-only checks, they change nothing. To see every cart rule whose window opens in the future or is currently live (adjust the ps_ prefix to your install):

-- Cart rules with their scheduled windows, soonest first.
SELECT id_cart_rule, code, active, date_from, date_to,
       quantity, quantity_per_user
FROM ps_cart_rule
WHERE date_to >= NOW()
ORDER BY date_from;

And to catch the classic "Valid to earlier than Valid from" mistake across every rule at once, before a customer finds it for you:

-- Any rule whose window can never open (to is before from).
SELECT id_cart_rule, code, date_from, date_to
FROM ps_cart_rule
WHERE date_to < date_from;

The equivalent for product price drops reads the ps_specific_price table. The from and to columns are the same scheduling fields the dialog writes, and a row with both set to 0000-00-00 00:00:00 is a permanent (un-dated) price, not a scheduled one.

The timezone trap that shifts your launch

This is the single most common way a scheduled discount goes wrong, and it is invisible until it bites. PrestaShop evaluates date_from / date_to against the store's configured timezone, set at International → Localization → Time zone (internally this is stored as PS_TIMEZONE). Which is not necessarily the same as your hosting server's system clock, and almost never the same as a customer browsing from another country.

The failure looks like this: your shop timezone is left at a default the host chose, or at UTC, while your business and customers run on CET (UTC+1). You set the sale to start at 00:00. To your customers in Central Europe, it actually goes live at 01:00, and the "midnight flash" everyone was emailed about is dead for the first hour. End times slip the same way: a "Sunday 23:59" cut-off in UTC ends at 00:59 Monday locally, giving away an extra hour you did not plan.

SymptomCauseFix
Promotion starts an hour late / earlyPS_TIMEZONE differs from your audience's timezoneSet the shop timezone to your primary market under International → Localization → Time zone, then set promo times in that timezone
You serve several countries across timezonesOne date_from cannot be midnight everywhereDecide whose midnight matters (usually your largest market) and pad start a few hours early / end a few hours late so no region is shorted
Dates look right but discount appears lateOld price is cached, not re-evaluatedSee the caching note below

Before any high-stakes launch, confirm the shop timezone first, then read your start time as "00:00 in that timezone" rather than "00:00 my time."

The detail almost everyone forgets: cache and the visual side

Two things sit between a correctly dated discount and a customer actually seeing it.

Caching. Because prices are computed at request time and then cached, a store running full-page cache, Smarty cache, or a CDN can keep serving the pre-sale price after date_from has passed, and keep serving the sale price after it ends. For a sale with a hard start, the safe pattern is to schedule the dates as normal and then clear the cache at go-live (Advanced Parameters → Performance → Clear cache) so the first render recomputes the price. If you run a long edge cache, factor its TTL into when you actually flush.

If your sale's start time is genuinely fixed (a midnight flash), you can take the human out of the cache flush too. PrestaShop doesn't schedule discount activation, but your server can schedule the cache clear. A one-line cron that runs the console cache-clear command at go-live, so the first post-launch render recomputes prices without you logging in:

# crontab entry: clear PrestaShop's cache at 00:00 on 27 Nov 2026,
# the minute a hard-start sale opens. Run as the web user.
# (path to the PrestaShop root; --no-debug for prod)
0 0 27 11 * cd /var/www/html && php bin/console cache:clear --env=prod --no-debug

That doesn't activate the discount, the date window does that on its own, it just guarantees the cached pre-sale page is gone the instant the window opens. On a CDN or edge cache you'd pair this with that provider's purge at the same minute. Treat it as belt-and-braces for sales where the first minute matters, not a requirement for everyday scheduling.

The visual side. The discount is scheduled; the homepage slider still says "Summer Sale" while the autumn promotion is live, or the banner advertising the code expired three days before the code did. Price scheduling and content scheduling are separate systems in PrestaShop, and the second has no native date fields on the default slider. Pair every scheduled discount with a scheduled creative swap so the message and the price change at the same minute, our banner approach for promotions covers producing those without a designer in the loop.

Overlapping discounts: what wins when two rules collide

The moment you schedule more than one promotion, you can stack them by accident. A product carrying a 20% specific price that also falls under a 15% automatic cart rule does not always behave the way a customer (or your margin) expects. PrestaShop resolves this with priority and combination settings rather than simply adding everything up:

  • Specific prices, when several could apply, conflicts are resolved by PrestaShop's specific price priority rules and matching criteria (shop/currency/country/group plus quantity and date matching); test the resulting product price.
  • Cart rules have their own Priority and a per-rule toggle that controls whether a rule can be combined with other vouchers in the same cart.
  • A specific-price reduction and a cart-rule discount are calculated at different stages (line price vs. cart total), so they can compound unless you intend them to.

The logic is genuinely fiddly and not worth reasoning about in the abstract. Before any window where promotions overlap, do the one test that settles it: place a real test order with the scheduled discounts active and read the final number. If it is larger than you meant, adjust cart-rule priority/compatibility, product restrictions, or exclude already-discounted products, then retest. The deeper mechanics of layering reductions live in the sale strategies guide; for products that should be fenced off from any scheduled discount, see discount exclusion.

A pre-launch checklist for any scheduled promotion

Set each promotion up roughly a week before it runs, so you are reviewing settings calmly rather than at 11 PM. Before it goes live, walk this list:

  • Dates read correctly. "Valid to" is genuinely after "Valid from," and both are in your shop timezone, not your wall clock.
  • Scope is right, a "20% off accessories" rule that quietly applies to the whole catalogue is an expensive afternoon. Confirm the category, group, or product condition.
  • Usage caps set, total available and per-user limits on any code that might leak.
  • Overlap tested, one real test order through the scheduled discounts; read the final total.
  • Cache plan. Know whether you are flushing cache at go-live and at end.
  • Creative scheduled, banner, slider, and any email timed to the same window as the price.

When the calendar gets bigger than the back office

Native date fields handle one promotion cleanly. The strain shows when you are running a rolling calendar, back-to-back seasonal sales, recurring weekend deals, time-boxed flash events, and you are now hand-editing dozens of cart rules and specific prices, each with its own timezone reasoning and cache flush. That is the workload our automation modules are built to remove. Sales Revolution runs scheduled, automatically-expiring flash deals as a managed campaign rather than a pile of manual rules. Set the window, the products, and the depth, and it handles starting and ending the deal; we introduced it in automated flash deals for PrestaShop. The benefit is the same one this whole article is about, scaled up: the on/off switch is no longer a person at midnight. For the psychology of running those time-boxed deals honestly, real countdowns, no fake-reset timers, see flash sales without manipulation.

The whole appeal of scheduled discounts is boring on purpose: you decide once, in daylight, with the dates and scope in front of you, and the store enforces them exactly. Get the timezone right, account for cache, schedule the creative alongside the price, and test the overlap, then let it run. Your future self at 11 PM on a Thursday will not have to think about it at all.

Scheduled discounts: common questions

Does PrestaShop need a cron job to turn a discount on at its start time?

No. Activation is not a scheduled job. There is no cron task that flips promotions on. PrestaShop stores a date_from/date_to on each cart rule and specific price and recalculates the price at request time, including the discount only when "now" falls inside the window. That's why a sale set for 00:00 genuinely starts at 00:00, with no job that can fail to fire. A cron is only useful for the cache flush at go-live, not for the discount itself.

My sale's date had passed but the old price kept showing, why?

Caching. Prices are computed at request time and then cached, so a full-page cache, Smarty cache or CDN can keep serving the pre-sale price after the window opens. Clear the cache at go-live (Advanced Parameters → Performance → Clear cache), and if you run an edge cache or CDN, purge it too and account for its TTL. For a hard-start sale, schedule that flush so the first post-launch render recomputes prices.

The promotion went live an hour late, what happened?

The timezone trap. PrestaShop evaluates the window against the store's configured timezone (PS_TIMEZONE, under International → Localization → Time zone), not the server clock or the visitor's local time. If your shop is left on UTC while your market runs on CET, a "00:00" start fires at 01:00 for your customers. Set the shop timezone to your primary market, then read every promo time as "midnight in that timezone".

Can I set a discount window with no end date?

Yes. Leave the To / Valid to field blank. On a specific price, clearing both date fields makes the price permanent (a standing markdown rather than a timed promotion). On a cart rule, an open-ended Valid to means the rule stays usable until you disable it or its usage caps run out. The date fields are precisely what turn a standing price into a timed one, so blanks are deliberate, not an oversight.

How do I stop two scheduled discounts from stacking into a loss?

Don't reason about it in the abstract, test it. Place one real order with both scheduled discounts active and read the final total. If it's deeper than intended, the levers are: cart-rule Priority, the per-rule "combine with other vouchers" toggle, and "Exclude discounted products" on a percentage cart rule so it ignores anything already on a specific price. Adjust, then retest. For SKUs that must never be touched by any promotion, see discount exclusion.

Share this post:
David Miller

David Miller

Founder, mypresta.rocks

David Miller is a PrestaShop specialist with over a decade of hands-on experience and the founder of mypresta.rocks, a software studio in Tychy, Poland. He builds and maintains a catalogue of 152 PrestaShop modules, including 21 "Revolution" suites spanning SEO, checkout, security, performance, marketing, search, support, and warehouse operations, that improve real stores every day, all tested against PrestaShop 1.7.8, 8.x, and 9.x. He also acts as caretaker for production stores turning over millions in annual sales, so his work is judged on live revenue, not demos. His experience runs the full breadth of ecommerce, performance, security, SEO, and marketing, and reaches beyond PrestaShop to WooCommerce, Shopify, and custom-built systems. On the blog he writes about the code-aware side of PrestaShop: what the platform really does under the hood, what breaks in production, and which fixes hold up.

Comments

No comments yet. Be the first!
Enjoyed this article?

Get our latest tips, guides and module updates delivered to your inbox.

You may unsubscribe at any moment. For that purpose, please find our contact info in the legal notice.

Loading...
Back to top