Telling expansion accounts from at-risk accounts in your Stripe feedback
Look at what each account's subscription has done in Stripe over the last billing cycle or two, not what plan they're on today. An account that just upgraded, added seats, or paid cleanly on the first attempt is trending toward more revenue. An account sitting in past_due status, mid a failed-payment retry, or with a downgrade already scheduled is trending the other way. Two accounts on the same plan, asking for the same feature, can be pointed in opposite directions, and Stripe's subscription and invoice events are exactly where that direction shows up first.
Plan tier alone won't tell you this. A $2,000/month account and a $2,000/month account look identical on a feature board until you check what each one's billing has been doing lately. Here's where that trajectory lives in Stripe, how to read it into a triage decision, and the point past which checking two dashboards by hand for every request stops being realistic.
Where the two signals live in Stripe
Stripe doesn't score accounts as "expanding" or "at risk." It records events, and the two that matter here are the same two categories Stripe already uses to calculate MRR growth on its own billing analytics page, expansion and contraction. The dashboard's downloadable Customer MRR changes report is described in Stripe's own docs as "a log of every MRR change for each customer, including new subscribers, upgrades, downgrades, reactivations, and churn," which is close to a ready-made feed for this if you're willing to pull it and join it by hand.
For a live signal instead of a monthly export, two webhook events carry the same information as it happens:
customer.subscription.updatedfires, per Stripe's event types reference, "whenever a subscription changes (e.g., switching from one plan to another, or changing the status from trial to active)." A price change on the subscription's items, seats going from 10 to 25, or a tier moving from Growth to Enterprise, comes through here. Compare the new price against what you have on file for that account; a jump is expansion, a drop is contraction.invoice.payment_failedfires, per the same reference, "whenever an invoice payment attempt fails, due to either a declined payment, including soft decline, or to the lack of a stored payment method." The invoice'sattempt_counttells you how many tries have already happened.
A failed payment doesn't mean the account is gone. Stripe's Smart Retries will keep attempting the charge on its own schedule, "8 tries within 2 weeks" by default, and plenty of failures are an expired card, not an unhappy customer. What the event does mean is that the account's subscription status has moved to past_due, which Stripe's subscription lifecycle docs define as "payment on the latest finalized invoice either failed or wasn't attempted." That status, sitting next to a feature request from the same account, is worth a second look before the request gets ranked the same as everyone else's.
The manual check, and where it breaks down
That comparison is repeatable as a five-minute check for any account that files a request:
- Open the account's subscription in Stripe and check the current status:
active,past_due,unpaid, or a scheduled downgrade waiting to apply. - Check the last 60 days of invoices for the account. A recent
invoice.payment_failedwithattempt_countclimbing, or a subscription sitting inpast_due, is the at-risk signal. - Check for a recent
customer.subscription.updatedwhere the new price is higher than the old one, seats added or a tier upgrade, which is the expansion signal. - Weigh the request accordingly. An expansion account's request is a hint about where the product needs to keep up with how the account is already growing. An at-risk account's request is sometimes a genuine blocker worth fixing fast, and sometimes noise from someone about to leave regardless; either way it shouldn't get weighted the same as a healthy account's ask by default.
- Route the account, not just the request, to whoever owns that relationship, growth or success, so the billing signal doesn't dead-end on the feedback board.
That routine holds up for a handful of requests a week, but it breaks down for reasons that have nothing to do with the data being hard to read:
- The check depends on someone remembering to do it. Nothing on the feedback board prompts it. Whoever triages the board that day files both requests as identical and never opens Stripe at all.
- Trajectory goes stale immediately. An account flagged healthy today can have a failed payment tomorrow, and nothing re-checks it unless a person does, by hand, again.
- The billing signal and the feedback board live in separate systems. Stripe has the subscription status; the feedback tool has the request; nothing ties the two together automatically, so the join happens in someone's head or not at all.
Keeping the trajectory attached to the request
Once a team is triaging more than a handful of requests a week, or feedback is arriving from more accounts than any one person can keep straight in their head, steps 1 through 3 above stop being something that happens every time and start being something that happens when someone remembers.
Automating that is one of the things Modem is built to do. Modem's Stripe integration keeps each company's plan and subscription status current on its record, alongside every feature request, support thread, and call note tied to that same account, refreshed as billing events happen rather than checked one dashboard at a time. Its Stripe automations already cover subscriptions starting, canceling, trials ending, and failed payments, so a request from an account with a failed payment sitting in that same window surfaces the connection automatically, next to whatever else is true of the account, instead of requiring someone to open Stripe first. I should say plainly that I work on Modem, so read that as an interested recommendation, not neutral advice; a manual check that's already covering your current volume fine doesn't need replacing just because a tool for it exists. Keeping billing status attached to the request instead of filed separately is the same context graph approach behind scoring requests by revenue in how to weight feature requests by Stripe ARR instead of vote count, and behind catching a downgrade before it lands in how to alert your team when a high-value Stripe account downgrades.
Whether or not automating it makes sense yet, the immediate test doesn't change. Pull the last five feature requests on your board and check each account's Stripe status, active and recently upgraded, or past_due with a retry pending. That alone splits requests you'd otherwise have weighted identically into two different conversations, which is the whole point of looking in the first place.
