4,000 Discount Codes, One API Call
Shopify has no native way to show only the coupons that apply to a given product and cart. We had thousands of codes and a support queue full of 'why didn't my coupon work.'
Context
The Sleep Company was running over 4,000 discount codes at once, across product-level deals, cart-level thresholds, combo offers, bank promotions, and date-based sale windows. For any single product, only four to six of those codes actually applied. Customers had no way to know which ones without trial and error at checkout, and every failed attempt became a support ticket or an abandoned cart.
The problem
Shopify doesn’t support this natively. There’s no built-in way to say “show me only the codes valid for this product, in this cart, right now.” The obvious approach, validating every code against the Storefront API on page load, doesn’t survive contact with 4,000 codes. It’s slow, and at that volume it risks hammering Shopify’s API rate limits on every single product page view.
The constraint
Whatever I built had to run silently, in the background, without slowing the page down or creating a new bottleneck for marketing. It couldn’t call the Shopify API once per code per pageview. It couldn’t require creating real test orders to check whether combo discounts were stacking correctly. And it had to handle codes that don’t exist as real Shopify discounts at all, like bank card offers and GST-linked promotions, alongside the ones that do.
The approach
I mapped the data flow before writing any code: admin picks the relevant campaign-aligned codes once, the frontend sends product ID plus current cart state, and the app spins up a virtual cart to validate every candidate code silently in the background. Only the codes that actually apply come back. One API call, one response, no guessing.
The harder part was underneath that flow. Combo discounts that stack differently depending on what else is in the cart. Priority logic for when multiple codes could apply and only one should win. Bank offers and GST coupons that needed to be represented in the same result set even though Shopify has no code for them.
The alternative I rejected was validating codes client-side against Shopify’s API directly, one call per candidate code. At 4,000 codes that’s not an edge case to guard against, it’s the default failure mode. Centralizing validation server-side, behind a single call, was the only version of this that scales.
One API call in, one filtered, priority-ordered response out
The result
The app has been running in production for over a year with zero API rate-limit issues from Shopify. Every product page now shows clean, cart-aware, priority-ordered coupons from every source, and the “why didn’t my coupon work” ticket volume dropped as a direct result.
What I’d do differently
I’d have put the priority logic behind an admin-configurable rules table from day one, instead of encoding it in application logic. The first time marketing wanted to run two competing campaigns simultaneously, that logic needed to change fast, and a rules table would have meant a config change instead of a deploy.