Tell us about your storeContact
Case study 03 · Subscription rescue

Out of stock shouldn't mean cancelled.

How a five-figure subscriber program stopped losing recurring revenue to its own catalog: stock-rescue swaps before a charge fails, vector-ranked replacements for discontinued products, and a human on every match.

77%of failed charges traced to one fixable cause
6% → 24%cancellation save rate, yearly average
Swap or switchthe customer decides, never a silent substitution

The problem

Subscriptions were about half of the store's revenue, and the catalog kept moving underneath them. When a subscribed item ran out of stock, the recurring charge failed. When a product was discontinued, the subscription died with it. Pulling the failed-charge queue showed that 77% of failures came from one cause: the item wasn't in stock on the day of the charge.

Nobody was offered an alternative before the charge, and the cancellation flow ended in a survey, not an offer.

Role and constraints

Bart Grudka ran the diagnosis from the subscription and charge data, then designed and built both systems as the store's Head of E-commerce. CANDEV builds the same for clients on Recharge and similar platforms.

  • The subscription platform stays the system of record. Nothing changes behind its back.
  • No silent substitutions. The customer chooses: swap, keep and wait, or switch.
  • A person approves every replacement for a discontinued product before it reaches a customer.
  • All customer messages go through the store's existing email platform, so tone, timing and unsubscribes stay in one place.

How it works

Scheduler runs ahead of charges Upcoming charges subscription API Stock check Shopify inventory Swap offer email platform Customer swap, keep, switch Discontinued SKU catalog change Similarity ranking Postgres + vectors Human approval admin view Subscription updated at risk choice applied ranked
Built for this systemExisting platform or partnerA person decides
1Watch

A scheduled job reads upcoming charges from the subscription API and checks stock for every subscribed item a few days ahead.

2Rescue

For items that won't be in stock on the charge date, the job picks a swap from the same product family and triggers an email: swap now, keep and wait, or switch.

3Apply

The customer's choice updates the subscription before the charge runs, so the charge succeeds and the parcel ships.

4Discontinued

When a subscribed product is retired, replacements are ranked by vector similarity over titles, attributes and descriptions, stored next to the catalog in Postgres.

5Approve

A person reviews the ranked candidates in an admin view and approves the match. Only then does the subscription move and the customer hear about it.

Rollout

Shadow mode first: the job logged what it would have offered, and those offers were checked by hand before any email was switched on. Then live behind per-capability switches, like everything else here.

Results, and how they were measured

MeasureBeforeAfterWindow
Failed charges caused by stockouts77% of the failed-charge queueOffered a swap before the chargelive charge-error queue at diagnosis
Cancellation save rate6%24%yearly average
Replacements for discontinued productsManual, ad hocRanked, human-approvedsince launch

The save rate is the share of subscribers who took an alternative instead of cancelling when they started to cancel, averaged over a year. It is a save rate, not subscriber retention. No dashboard screenshots here by design: the store's figures stay private, the architecture and the deltas don't.

What it took

Next.jsPostgres + vector embeddingsRecharge APIKlaviyoShopify Admin APICloud Scheduler
Have the same problem? Tell us what's manual, what's breaking, what Shopify won't do. One email is enough to start. We reply within one business day with questions or a plan.