Two Discounts Stacked and the Merchant Ate the Margin
The merchant noticed it in the payout, not in the store. A handful of orders carried two discounts that had never been designed to coexist, an automatic ten percent off and a welcome code for fifteen, applied to the same cart, compounding into a price nobody had authorised.
Nobody had misconfigured a single discount. Each one was created correctly, tested correctly and behaved correctly in isolation. The defect was in the combination, and the combination was governed by a setting with a default that surprises everyone the first time.
This was observed on a Shopify store with automatic discounts and discount codes, checked in Chrome 133, and reproduced on a second store before I trusted that it was a pattern rather than a one off.
The default that surprises
Shopify discounts have a combinability model, and the default is more permissive than merchants expect. Automatic discounts and discount codes can combine unless you explicitly say otherwise, and within the model, the store decides which discount types stack.
So the merchant who creates an automatic promotion and, separately, a welcome code, has created a stackable pair by default. Each was reviewed alone. The pair was never reviewed, because the pair is not visible in either discount's settings screen. It only exists at checkout, in the combination engine.
This is the configuration version of the two limits problem in 413 request entity too large with two limits: each rule is correct in isolation, and the composition is the bug.
Why testing misses it
Discounts get tested the way everything gets tested, in isolation. Someone applies the code, it works. Someone watches the automatic discount trigger, it works. The combination requires adding both to one cart in one test, and there is no screen that lists the combinations, so the test matrix never includes the pair.
The number of pairs grows with the number of discounts. Three discounts is three pairs. Ten discounts is forty five pairs, plus triples. No merchant tests the combinatorial space, which means the combinations are untested by construction, and the defaults govern production.
The money shape of the bug
The compounding matters. Ten percent then fifteen percent is not twenty five percent. It is 0.9 times 0.85, which is 23.5 percent off, and if the two discounts were assumed mutually exclusive in the pricing model, the margin calculation was built on a price that never happens for the stacked carts.
Worse, some stacks interact with shipping and free shipping discounts, where the combination can zero out revenue on an order that still costs real money to fulfil. The merchant pays for shipping on an order that made almost nothing, which is how a "promotion" becomes a per order loss.
The fixes
Make exclusivity explicit at creation. Every discount gets a written rule about what it may combine with, and the combinability settings are set to match, not left at default. The rule belongs in the discount's own description, so the next person who creates a discount sees the policy next to the setting.
Treat automatic discounts as the riskier half. Codes require a customer to know them, which bounds their blast radius. Automatic discounts apply to everyone, so an automatic discount that stacks with every code is standing open to every code you will ever issue. Review automatic discounts against the whole code book, not against nothing.
Add the combination test. The matrix is large, so test the pairs that matter: every automatic discount against every active code. That is a tractable list, and a scripted checkout that asserts the final price for each pair turns the untested space into a monitored one. When a new code is created, it runs against the automatic set before it goes live.
Alert on the money, not the settings. Configuration review prevents, but detection catches what slips through. Alert when an order carries more than one discount, or when the effective discount percentage crosses a threshold. The payout anomaly that found this bug can be an alert instead of a discovery, which is the difference between a Tuesday fix and a quarter of margin loss.
The review checklist
For any store with more than a couple of discounts, ask three questions. Is combinability set explicitly on every discount, or are defaults governing checkout. Is there a written policy naming which discounts may stack. And is there a test or an alert covering the automatic times code pairs.
If the answer to all three is no, the store is not running a promotion strategy. It is running a set of independent promotions whose interactions are decided by software defaults, and the defaults were not chosen by anyone, which is the most expensive kind of unmade decision there is, because it prices real orders while nobody is looking.
The rule
Discount combinability is a policy, and a default is an unmade decision. Set it explicitly, test the pairs that carry money, and alert on the effective discount so the composition is observed in production, because the combination of two correct discounts is the one combination nobody ever looks at, and it is the one that prices the order.
There is also a scheduling dimension that catches stores at the worst moment. Promotions are created around campaigns, and a campaign's automatic discount often outlives the campaign in the settings, still active, still stackable, waiting for the next code to combine with. A quarterly audit that disables expired automatics is not housekeeping, it is margin protection, because an expired promotion that still applies is a standing offer you are funding.
The broader lesson, that independently correct rules compose into incorrect outcomes, is the timeout ladder story in 504 gateway timeout while your application was still working, where each timeout was fine and the stack was not.