Countdown timers that stop when the discount stops
A countdown timer is a promise that the price ends at a given moment. How to make Magento 2 timers follow the real promotion, and run a sale to the minute.
Most people have seen it at least once. A product page says "Offer ends in 00:14:59", you go and make a cup of tea, come back, reload, and it says "Offer ends in 00:14:59" again. Or the timer reaches zero, and the price is still the sale price the next morning. Either way, you stop believing timers on that site, and probably a little on every site.
A countdown is a promise: this price ends at this moment. The only timer worth showing is one that is true. This post is about making that easy to get right on Magento 2: where Magento keeps sale dates, why a timer and a price can disagree, and how our Flash Sale Countdown module ties the two together.
Where Magento keeps the sale dates
On a Magento store a sale is usually one of three things. A catalog price rule lowers the price of a set of products. A cart price rule gives a discount in the cart. Or products get a special price with Special Price From and To dates.
The catch is that the rule dates are days, not times. In Magento's database the From and To columns of catalog price rules and cart price rules are date columns, without hours or minutes1. A rule runs for whole days in the store's time zone. That is fine for "20% off all week". It does not cover "25% off bags from 18:00 Friday until 18:00 Saturday", which is what most flash sales are. Merchants work around it by switching the rule on and off by hand, which works until the person who was meant to do it at 18:00 is on a train.
A countdown timer added separately, through a theme widget or a script with an end time typed in, has the problem from the introduction: it knows nothing about the rule. If the rule is switched off early, or its date is changed, the timer carries on.
Linking every timer to a real promotion
In Flash Sale Countdown there is no such thing as a free-standing timer. Every flash sale is linked to a promotion: a catalog price rule, a cart price rule, the special prices of chosen products, or a campaign of Promo Scheduler. The timer is shown only while that promotion actually gives its discount, and it disappears when the promotion ends or is switched off. There is no setting for a timer without a live discount behind it.
For timing you choose one of two modes. "Use the linked promotion's dates" follows the rule's From and To dates (whole days, in each store view's time zone) and only while the rule is active; a rule without a To date has no countdown, because there is nothing true to count down to. "This sale's dates" lets you enter a start and an end with hours and minutes. The module then switches the linked rule on at the start and off at the end by cron, to the minute. Only that rule's products are reindexed, and the page cache of the affected products and categories is cleaned, so the price and the timer change together.
Two details are worth knowing. If you switch the rule off by hand during the sale, it stays off and the timer goes with it; the module does not fight you. And disabling or deleting a running sale switches its rule off.
What shoppers see
The timer appears next to the price on product pages (boxed or compact), as an "Ends in 05:12:09" badge above the price in category lists, in an optional campaign bar at the top of every page with your text and link, and in a CMS widget. You can show the listing badge only in the last few hours of a sale if a whole week of badges feels like too much.


A "Starts in" teaser can run a chosen number of hours before a start, but only a confirmed one: a sale with its own dates, an active rule with a future From date, future special prices or an upcoming scheduled campaign. A rule that is switched off with a future date is not confirmed, so no teaser is shown for it.
Timers carry the absolute end time and count down in the browser, so cached pages stay correct, and the shopper's clock is corrected once per session against the server time. A visitor whose laptop clock is ten minutes fast still sees the right time left.
The stock indicator, and what it will not say
Under the product timer you can show "Only 4 left" when the salable quantity is at or below a threshold, or "73% sold", worked out either from the stock at the start of the sale or from the sale's own orders against a sale quantity you set per product. When Multi-Source Inventory is installed, salable quantity comes from it.
The rule here is the same as for the timer: nothing is shown when the numbers are not known. There is no option for a made-up percentage. One limitation in the current version: "% sold" from orders takes cancelled orders off again but does not take refunds off.
Limits and when you do not need it
If your sales run in whole days, Magento's own rule dates and an honest banner may be all you need. The module earns its place when you need hours and minutes, or timers on many products that must match the real price.
Cart price rule conditions and scheduled campaign rules are not evaluated, so for product timers on those you enter SKUs or categories on the sale (the bar and the widget work without them). A sale's own start and end are entered in the default scope's time zone. Special prices on the children of a configurable product show no timer on the parent. Timers need JavaScript to count down; without it the time left when the page was created and a text alternative are shown. And it all depends on cron: if cron does not run, rules are switched late, and a start missed entirely is not made up after the end.
If you plan several sales across a day, such as different discounts every six hours on Black Friday, Promo Scheduler handles the switching and Flash Sale Countdown can show a timer for each of its campaigns.
The Flash Sale Countdown module page has the full settings, the status list and more screenshots.
Sources
- Magento Open Source 2.4.9 source code,
app/code/Magento/CatalogRule/etc/db_schema.xmlandapp/code/Magento/SalesRule/etc/db_schema.xml(from_dateandto_datearedatecolumns), checked 12 October 2026. ↩
From our shop