Automate Stripe Plan Downgrade → Instant Retention Intervention in n8n — Step by Step
A customer just dropped from your $99/month Pro plan to the $29 Starter tier. In Stripe, that event is a single line in a webhook payload. In your revenue, it's the first visible symptom of a churn th
A customer just dropped from your $99/month Pro plan to the $29 Starter tier. In Stripe, that event is a single line in a webhook payload. In your revenue, it's the first visible symptom of a churn that probably started weeks ago. The gap between those two facts — the downgrade happening and your team noticing — is where retention dies. Most SaaS teams find out about downgrades at the end of the month when someone runs an MRR report. By then the customer has mentally checked out, the renewal is already discounted, and any "we noticed you scaled back — can we help?" outreach lands as a form letter instead of a timely save.
This article walks through a production-ready n8n workflow that closes that gap to seconds: detect every Stripe plan downgrade the moment it happens, alert your team in Slack, fire a personalized retention email, and flag the contact as at-risk in HubSpot — with no human in the loop until a human actually needs to intervene.
Why plan downgrades are your highest-signal churn event
Cancellations get all the attention, but a downgrade is a better early-warning signal than an outright cancel. A downgrade means the customer still sees some value — they didn't leave — but they've decided your product is worth less than they were paying. That's a negotiable position. It's the window where a well-timed message ("Noticed you moved to Starter — was there a feature that wasn't pulling its weight?") can recover the relationship, uncover a fixable problem, or at minimum give you the churn reason your product team desperately needs.
The problem is purely operational: Stripe knows the instant a subscription's plan changes, but that knowledge sits inside Stripe unless something pulls it out and routes it to the humans and systems that can act. Downgrades are also easy to miss because they don't reduce your customer count — the logo stays on the wall while the revenue quietly bleeds. Net revenue retention erodes one silent downgrade at a time. Automating detection means every downgrade gets the same fast, consistent response instead of depending on whoever happens to be watching the Stripe dashboard.
The solution: a four-action automation triggered by Stripe
The workflow does four things the moment a downgrade is confirmed:
- Detect — listen for Stripe's
customer.subscription.updatedevent and confirm the plan actually went down in price, not up or sideways. - Alert — post a structured message to a Slack channel so your CS or founder-led sales team sees it in real time.
- Intervene — send the customer a personalized retention email while the decision is fresh.
- Tag — set an "at-risk" property on the contact in HubSpot so the churn signal lives in your CRM and drives future sequences.
Everything runs on n8n, so you own the logic, the data never touches a third-party SaaS you can't audit, and you can extend any branch without waiting on a vendor roadmap.
Step-by-step setup in n8n
1. Trigger — Stripe Trigger node. Add a Stripe Trigger node and subscribe to the customer.subscription.updated event. n8n registers the webhook with Stripe automatically using your Stripe API credentials, so you don't manually configure endpoints in the Stripe dashboard. This event fires on every subscription change, which is exactly why the next step matters.
2. Confirm it's actually a downgrade — IF node. The subscription-updated event fires for upgrades, quantity changes, and metadata edits too. Add an IF node to isolate real downgrades. Stripe's payload includes data.previous_attributes, which only contains the fields that changed. Compare the new plan amount against the previous one:
- Condition:
{{ $json.data.object.items.data[0].price.unit_amount }}is smaller than{{ $json.data.previous_attributes.items.data[0].price.unit_amount }}
If previous_attributes doesn't contain a price change, it wasn't a plan downgrade and the IF node's false branch simply ends the run. This guard is the single most important node in the workflow — skip it and you'll spam Slack on every renewal and metadata tweak.
3. Enrich the customer — Stripe node (get customer). The subscription object carries a customer ID but not their email or name. Add a Stripe node set to Customer → Get, passing {{ $json.data.object.customer }}. Now you have the email, name, and any metadata you need for the Slack message and the retention email.
4. Alert the team — Slack node. Add a Slack node (Message → Send) pointed at a dedicated channel like #retention-alerts. Use Slack's Block Kit or a clean text message with the essentials so the team can act without opening Stripe:
- Customer name and email
- Old plan → new plan, with both dollar amounts
- The MRR delta (e.g., "−$70/mo")
- A direct link to the customer in Stripe:
https://dashboard.stripe.com/customers/{{ $json.id }}
5. Send the retention email — Send Email or Gmail node. Add a Send Email (SMTP) or Gmail node. Keep the copy human and specific — reference that they moved to the Starter plan, ask one genuine question, and offer a real path back (a call, a discount, or help with the feature they abandoned). Personalize with expressions like Hi {{ $json.name }},. The goal is a reply, not a broadcast, so send it from a real person's address and keep it plain-text in tone.
6. Flag at-risk in HubSpot — HubSpot node. Add a HubSpot node (Contact → Create or Update), match on the customer's email, and set a custom contact property such as lifecycle_risk to at_risk, plus a downgrade_date timestamp. Create the property in HubSpot first if it doesn't exist. Now the signal is durable: your CRM can drive win-back sequences, your CS team can filter on it, and your reporting reflects reality.
Wire the nodes in sequence — Stripe Trigger → IF (true branch) → Stripe Get Customer → Slack → Send Email → HubSpot — and activate the workflow. Test it by downgrading a test-mode subscription in Stripe and watching all four actions fire.
What you get out of it
Speed. The intervention window collapses from weeks to seconds. You reach the customer while the decision is still fresh and reversible.
Consistency. Every downgrade gets the same fast response regardless of who's online, what day it is, or how busy the team is. No downgrade slips through a month-end report.
A churn-reason dataset. Because every downgrade prompts an email, replies accumulate into a structured record of why customers scale back — the single most valuable input your product and pricing decisions can have.
CRM truth. Retention risk lives in HubSpot, not in one person's head, so it survives handoffs and compounds into better sequences over time.
Common pitfalls to avoid
Skipping the downgrade check. The number one mistake is treating every customer.subscription.updated event as a downgrade. Without the IF-node price comparison against previous_attributes, you'll fire on upgrades and metadata changes and quickly train your team to ignore the channel. Guard rigorously.
Comparing against the wrong baseline. Always read the old price from data.previous_attributes, not from a stored value or the current object. previous_attributes is Stripe's authoritative "what changed" — using anything else invites race conditions and false positives.
Multiple subscription items. If your customers can have several line items or add-ons, items.data[0] may not be the plan that changed. For multi-item subscriptions, loop over the items or compare total subscription amounts rather than assuming index zero.
Emailing on test events and duplicates. Stripe can retry webhooks, and test-mode traffic can leak into a live workflow. De-duplicate on the event ID and confirm you're keying credentials to live vs. test correctly, so a single downgrade never triggers three emails.
Sending a robotic email. A generic "We're sorry to see you go" template performs worse than no email at all — it signals automation and kills the reply. Write copy a founder would actually send, ask one real question, and make replying easy. The automation should feel like a fast human, not a bot.
No fallback if enrichment fails. If the Stripe customer lookup or HubSpot match fails, don't let the whole run die silently. Add an error branch or an error-workflow so a failed lookup still posts to Slack — a partial alert beats a missed downgrade.
Set this up once and every future downgrade routes itself: your team sees it, the customer hears from you, and your CRM records the risk — all before anyone has to remember to check.
Ja construimos isso pra voce
Nao comece do zero. O Stripe Plan Downgrade → Instant Retention Intervention e um workflow n8n pronto para instalar — conecta suas ferramentas em minutos, sem codigo.
Instalar por $59 →