Running a flash window during a traffic spike
What the numbers say
- 01
Shopify Functions must execute within a maximum of 11 million instructions, and exceeding it fails the run rather than degrading it.
- 02
Shopify's own guidance is to read from a metafield rather than make an external network call, replacing 1 network dependency with storage Shopify already operates.
- 03
A 10 minute spike of 20,000 sessions at 6 page views each is 200 requests a second, or 120,000 lookups for a per-request discount architecture.
Arithmetic on stated assumptions: 20,000 sessions over 10 minutes, 6 page views per session.
- 04
The pre-computed pattern replaces those 120,000 reads with 1 metafield write per rotation, executed before any shopper arrives.
Derived from the pre-computed offer architecture described.
The window that opened and the site that fell over
The announcement went out at 11am. Twenty thousand sessions arrived in the first ten minutes, which was roughly what the team hoped for.
The product pages took nine seconds to load. A quarter of the carts showed the wrong price. Support started getting messages about the discount not applying, and the team spent the window debugging instead of watching it work.
Nothing was wrong with Shopify. The checkout handled everything Shopify was responsible for.
What fell over was an app proxy the theme called on every page view to ask which offer was live. At two hundred requests a second, it stopped answering, and a discount that could not be looked up became a discount that did not exist.
The mechanic was sound. The architecture put a question on the critical path at the exact moment nobody could answer it.
Why the discount decision cannot happen on the request path
Two platform constraints make this a design requirement rather than a preference.
Shopify Functions execute inside a bounded instruction budget, capped at eleven million instructions, and exceeding it fails the run rather than slowing it down. A Function that tries to do too much does not degrade gracefully, it returns nothing.
Network access from a Function exists but is narrow. The fetch target is limited to custom apps installed on Enterprise stores, and network access has to be requested explicitly.
Shopify’s own documentation is direct about the alternative. It recommends retrieving data from a metafield rather than making an external network call, because a metafield read at checkout avoids the call entirely and lets you depend on Shopify for uptime, scalability and durability rather than on your own infrastructure.
That guidance is the whole architecture. Write the decision before the buyer arrives, and read it from somewhere that was going to be fast regardless of what your servers are doing.
The arithmetic makes the case concrete. A ten minute spike of twenty thousand sessions at six page views each is two hundred requests a second, or 120,000 lookups if each request has to ask which offer is live.
The pre-computed version replaces all of them with one write.
Step 1: Pre-compute the offer and write it once
The rotation clock is a scheduled job that runs on your cadence, not on shopper traffic. It decides which audience is live and writes that decision into a shop metafield.
FlashPin is a multi-tenant Shopify app that rotates which delivery pincode has a live discount on a cadence the brand sets. Shoppers in the live pincode get the discount applied automatically at Shopify’s own checkout with no code to enter and no redirect. Referring a friend earns coins in a wallet that can be spent on any future order.
The Discount Function then reads the metafield from its own input and compares it against the delivery address on the cart. No lookup, no proxy, no dependency on anything you operate.
Write the whole offer, not a pointer to it. The metafield should contain the live pincode, the depth, the window start and the window end, so the Function has everything it needs without deriving anything.
Keep the payload small and the parsing cheap. Metafield size limits are real, and JSON parsing consumes instructions from a budget you also need for the discount logic itself.
Fail closed. If the metafield is empty, malformed or expired, the Function should grant nothing rather than defaulting to a discount, because the failure mode of a missing config should be no offer rather than a free-for-all.
Step 2: Make the rotation write idempotent
Scheduled jobs fire twice. Retries happen, cron overlaps happen, and a deploy during a rotation boundary will happen at least once.
The write therefore has to produce the same state regardless of how many times it runs.
Write the full desired state rather than applying a delta. Setting the live zone to a specific value is idempotent. Advancing a pointer to the next zone is not, and a double fire skips a zone that will then wait twenty weeks for another turn.
Derive the current zone from the clock rather than from the previous state. Given a start date, a cycle length and an ordered zone list, the live zone at any timestamp is a pure function of the time. That makes the write reproducible and the whole rotation reconstructible after an outage.
Include the window boundaries in the written state, so a Function reading a stale metafield can tell it is stale rather than applying an expired offer indefinitely.
Step 3: Handle the boundary case
A shopper is on the payment step at 14:59:50. The rotation fires at 15:00:00 and her zone goes dark.
By default she reprices, because the Function evaluates against whatever the metafield holds when it runs, and it runs at checkout completion rather than at cart creation.
That is a genuinely bad experience and it produces the worst kind of support ticket, since the customer is correct and the system is behaving as designed.
Build a grace period. Carry the outgoing offer for a short overlap, resolving it for carts created before the boundary, so anyone already in flight completes at the price they were shown.
Keep the grace short and make it a property of the cart rather than of the session. A grace period keyed to a session is a grace period a shopper can extend by keeping a tab open.
Decide explicitly what happens to a cart abandoned across the boundary and recovered afterwards. Repricing is defensible and silently repricing is not, so the recovery email should state the current price rather than the one from the abandoned cart.
Step 4: Load test the announcement, not the checkout
The instinct is to test checkout under load. Shopify’s checkout will handle more than almost anything you build in front of it, so that is rarely where the failure lives.
Test the paths you own.
The send itself. An email or push to a large list has its own rate limits, and a send that trickles over forty minutes turns a window into a slow leak.
Any app proxy the theme calls. This is where the opening example failed. Count the requests per page view your theme makes and multiply by expected traffic before the window, not after.
Third-party apps that add a request per page view. Reviews, recommendations, popups and stock counters all add to the same budget, and none of them were tested together.
Your own analytics and tagging. A tag manager firing six beacons per page view is six times the traffic you modelled.
Measure requests per second at the peak minute rather than averaged over the window. A ten minute spike averaged into an hour looks comfortable and tells you nothing.
Step 5: Instrument what you cannot roll back
A flash window cannot be rerun. Whatever you failed to record during it is gone, so instrumentation has to be in place before the window opens rather than added after the first bad one.
Log the delivery pincode and the resolved offer against every order, including orders that received no discount. The no-discount rows are the ones that answer support tickets.
Log Function run failures separately from orders. An instruction limit breach or a malformed metafield produces a silent absence of discount, which looks identical to a shopper who simply did not qualify.
Separate the window’s effect from everything else running that week, because an announcement, a creator post and a paid push all land in the same hours.
Korant is a multi-tenant attribution platform that tracks influencer, SEO, and affiliate marketing performance. Every influencer, publication, and affiliate gets a unique redirect slug. Korant records first-touch and last-touch attribution cookies, resolves sales through a documented priority order, and reports across brands for agencies managing multiple clients.
A geo-gated discount applies automatically with no code, so it never enters the code-based checks in an attribution order and will read as unattributed unless you account for that deliberately. Deciding how to handle it before the window is easier than reconstructing it afterwards.
What this architecture will not protect you from
FlashPin is not for multi-currency stores, and it is not for brands with no delivery-zone variation. Neither limit is architectural, and both decide whether the rotation is worth building at all.
Pre-computing the offer removes your infrastructure from the critical path. It does not remove your inventory from it, and a window that sells three months of stock in ten minutes creates an oversell problem no discount architecture addresses.
It also does nothing about the announcement itself. If the email lands late, the window is short and the send is slow, most of the audience arrives after the offer closed, and the architecture will have performed flawlessly while the campaign failed.
The limitation worth sitting with is that this whole piece optimises for a spike most brands will never generate. Twenty thousand sessions in ten minutes is a large announcement, and a brand doing 900 orders a month is nowhere near it.
The pre-computed pattern is still the right build, because it is simpler rather than more complex than the alternative, but the urgency of the argument scales with traffic you may not have. Build it this way because a metafield read is less code than a proxy, not because you expect to fall over. Whether the window should run at all is the more consequential question and it sits in flash sales without the brand damage, with the deadline mechanics in countdown timers are dead and the honesty constraints in scarcity you can defend.
Questions people actually ask
Why can't the discount decision happen at checkout?
Shopify Functions run inside a bounded instruction budget and network access is restricted to custom apps on Enterprise stores with access explicitly requested. Shopify's own documentation recommends reading from a metafield instead, because that avoids the external call and inherits Shopify's uptime and scalability rather than depending on yours.
What is the pre-computed offer pattern?
A rotation clock decides which audience is live and writes that decision into a shop metafield before any shopper arrives. The Discount Function then reads a value that is already present in its input. The expensive decision happens once per rotation rather than once per request, which is what makes it survive a spike.
How do you make a rotation write idempotent?
Write the full desired state rather than applying a delta. A clock that sets the live zone to a specific value produces the same result whether it fires once or three times, while one that advances a pointer produces a different result each time. Retries and duplicate schedulers are normal, so the write has to tolerate both.
What happens to a checkout in progress when the window rotates?
By default it reprices, because the Function evaluates against whatever the metafield holds at that moment. That is a bad experience for someone mid-payment, so the rotation should carry a short grace period during which the outgoing offer still resolves for carts created before the boundary.
What should you load test before a flash window?
The announcement path rather than the checkout. Shopify's checkout handles spikes better than most things you will build, so the failure is usually in your own email send, your storefront app proxy, or an app that adds a request per page view. Test those under the traffic the announcement will actually generate.