n8n Churn Prevention: Score At-Risk Subscribers Before They Cancel
n8n churn prevention scores subscriber risk daily, flags at-risk accounts early, and fires tiered campaigns before cancellation happens. Browse templates.
Churn Announces Itself Before It Happens
Most cancellation events look sudden from the Stripe dashboard. They aren't. The signals arrive two to four weeks earlier: logins drop from daily to twice a week, then stop. A payment fails and the card doesn't get updated. A user downgrades their plan and goes quiet.
None of those events fire an alert by default. That's the problem.
n8n churn prevention works at the behavioral layer, not the billing layer. A daily workflow scores every active subscriber against four risk factors, classifies them into risk tiers, and sends the right message at the right moment — a warm check-in for at-risk accounts, a personal discount offer for critical ones, a real-time win-back email for those who've already cancelled. The intervention window is still open. You just need to reach it.
The Membership Churn Recovery Engine scores every member daily using login frequency, failed payments, card expiry, and plan change history. It classifies accounts into four tiers (safe, at-risk, critical, churned), generates AI-personalised emails with GPT-4o-mini for each tier, sends outreach via Gmail or SMTP, logs every touchpoint to Google Sheets, and posts a daily Slack summary of emails sent by tier. Ten minutes to set up, fully automated after that.
What n8n Churn Prevention Can Automate
Every high-leverage intervention in the retention lifecycle can be handled by an n8n workflow:
- Daily engagement scoring — compute a 0–100 churn-risk score for every active subscriber using login recency, failed payment count, card expiry, and plan direction
- Tiered retention outreach — route accounts to safe/at-risk/critical/churned tiers and send tier-appropriate messages: warm nudges, personal discount codes, or win-back campaigns
- Payment failure interception — detect a failed charge via Stripe webhook within minutes, send a dunning email, and flag the account on Slack before the grace period expires
- Card expiry early warning — catch subscribers whose card expires in the next 30 days and prompt them to update before the charge fails
- Cancellation win-back — fire a personalised win-back email within 24 hours of cancellation, while the decision is still fresh
- Daily Slack digest — get a concise summary of accounts moved between risk tiers and how many outreach emails went out
The Churn Prevention Pipeline
Every n8n churn prevention workflow follows the same backbone:
Schedule Trigger (daily) → Google Sheets (read members)
→ Code (compute risk score + assign tier)
→ Switch (safe / at-risk / critical / churned)
at-risk → Gmail (warm check-in email)
critical → OpenAI + Gmail (AI discount offer)
churned → OpenAI + Gmail (AI win-back email)
→ Google Sheets (log campaign event)
→ Slack (daily summary)
The Schedule Trigger runs once at 08:00 each morning. All tiers pass through the same Switch node, so the scoring logic is centralised. Safe accounts are filtered before any email node is reached.
1. Collect Behavioral Signals
The workflow reads your Google Sheets member database. Each row needs at minimum: email, last_login_date, failed_payment_count, card_expiry_date, plan_change_direction, and last_contacted_date.
The last_contacted_date field is critical. Without it, the same at-risk member gets an email every single day the workflow runs. It's the field most builders forget on the first pass. Costly mistake when your member list is a few hundred rows.
2. Score Churn Risk
A Code node (v2, jsCode field) computes the risk score per member. Here's a working implementation:
const now = Date.now();
const msPerDay = 86400000;
const daysSinceLogin = Math.floor(
(now - new Date(item.json.last_login_date).getTime()) / msPerDay
);
const daysSinceContacted = Math.floor(
(now - new Date(item.json.last_contacted_date || '2000-01-01').getTime()) / msPerDay
);
const daysUntilExpiry = Math.floor(
(new Date(item.json.card_expiry_date).getTime() - now) / msPerDay
);
const score =
(daysSinceLogin > 14 ? 40 : daysSinceLogin > 7 ? 20 : 0) +
(item.json.failed_payment_count > 0 ? 30 : 0) +
(daysUntilExpiry > 0 && daysUntilExpiry < 30 ? 15 : 0) +
(item.json.plan_change_direction === 'downgrade' ? 15 : 0);
const tier =
score >= 70 ? 'churned' :
score >= 40 ? 'critical' :
score >= 20 ? 'at-risk' : 'safe';
// Skip accounts contacted within the last 7 days
if (daysSinceContacted < 7) {
return [];
}
return [{ json: { ...item.json, churnScore: score, tier } }];
The return [] for recently-contacted members is how n8n drops items cleanly. Returning an empty array from a Code node v2 removes the item from all downstream processing. Don't return null or undefined — those throw a parse error, and the workflow logs it as an execution failure rather than a graceful skip.
Days since last login gets the highest weight because inactivity is the single strongest leading indicator across B2C and SMB SaaS products. Failed payments score 30 — high, but billing issues often resolve quickly when the customer is prompted. Card expiry and plan downgrades each score 15: real signals, but neither is as predictive on its own as a subscriber who simply stops showing up. The four-factor model catches roughly 80% of churns that would otherwise be invisible until Stripe sends the cancellation webhook.
3. Route by Tier
A Switch node reads $json.tier and routes each account to its outreach path. Four output connectors: safe (no action), at-risk, critical, churned. The safe branch terminates. Don't connect it to anything downstream, not even a Sheets log row. At scale, logging "safe" events adds thousands of writes per month for no operational value.
4. Send Tier-Specific Outreach
At-risk accounts get a plain-text check-in: "We noticed you haven't logged in recently — anything you need help with?" No discount. No pressure. Critical accounts get an AI-generated email from the @n8n/n8n-nodes-langchain.openAi v2.1 node that includes a personal discount code. That node's output arrives at $json.output[0].content[0].text — not $json.text or $json.message, both of which appear in older tutorials and fail silently when the response lands empty.
Churned accounts get a win-back email that references what they built on the platform. You'll need to pass usage history into the prompt for this tier. Generic "come back" emails don't convert. A message that says "you set up three automated reports in February" does.
5. Log and Alert
Every outreach event writes a row to a CampaignLog Google Sheets tab: email, tier, subject line, timestamp, and whether a discount code was included. Without this log, you can't tell if your critical-tier emails are recovering accounts or being ignored. The Slack node posts the day's summary: emails sent per tier and how many members shifted from at-risk to critical since yesterday's run.
Implementation Patterns
Pattern 1: Stripe Webhook Win-Back
For real-time win-back within minutes of cancellation, replace the Schedule Trigger with a Webhook node receiving Stripe's customer.subscription.deleted event. The workflow receives the cancellation payload, pulls the customer's last active plan, generates a personalised win-back offer with OpenAI, and sends it in under five seconds.
Webhook (customer.subscription.deleted)
→ HTTP Request (fetch customer usage history from your product API)
→ OpenAI (write personalised win-back email referencing last plan + usage)
→ Gmail (send)
→ Google Sheets (log cancellation event + outreach timestamp)
This path and the daily batch path aren't alternatives — they're complements. The daily batch catches at-risk accounts before they cancel. The webhook catches accounts the moment they do. Both are needed for a complete retention system.
Pattern 2: Segment by Member Tenure Before Routing
The single worst mistake in n8n churn prevention is treating every at-risk account identically. A member who hasn't logged in for 12 days after 18 months of active use is a completely different intervention than a member who went quiet after day 3. The risk score is the same. The message can't be.
Add one line to the Code node to calculate tenure:
const tenureMonths = Math.floor(
(now - new Date(item.json.signup_date).getTime()) / (msPerDay * 30)
);
return [{ json: { ...item.json, churnScore: score, tier, tenureMonths } }];
Then add a second Switch or IF node that branches at-risk accounts by tenure before routing to email. Long-tenure at-risk accounts (6+ months) get a personal check-in that acknowledges their history with the product. Short-tenure at-risk accounts get a feature highlight that might re-engage someone who hasn't fully explored the product. The Membership Churn Recovery Engine handles tiered outreach out of the box — tenure segmentation is the layer you'd add on top.
In practice, the first 24 hours post-cancellation are the highest-conversion window. That's when the decision is still fresh. Waiting until the next morning's batch run at 08:00 means missing a 6–18 hour real-time window for many cancellations that happen during evening usage. That's why the Stripe webhook path exists as a separate workflow, not a branch inside the daily batch. The timing difference is the whole point.
n8n Nodes You'll Use Most
| Node | Version | Purpose |
|---|---|---|
| Schedule Trigger | v1.2 | Run daily scoring at 08:00 |
| Google Sheets | v4.x | Read member records; log campaign events |
| Code | v2 (jsCode) | Compute churn-risk score and assign tier |
| Switch | v3 | Route by tier (safe / at-risk / critical / churned) |
@n8n/n8n-nodes-langchain.openAi | v2.1 | Generate AI-personalised retention and win-back emails |
| Gmail / Send Email | v2 | Dispatch tier-specific outreach |
| Slack | v2 | Post daily risk-tier summary |
| Webhook | v1 | Receive Stripe cancellation events in real time |
| HTTP Request | v4.2 | Fetch customer usage history from your product API |
Getting Started
- Deploy the Membership Churn Recovery Engine — it ships with daily scoring, tiered email outreach, Google Sheets logging, and the Slack summary pre-built.
- Set up a Google Sheets member database with at least:
email,last_login_date,failed_payment_count,card_expiry_date,plan_change_direction,last_contacted_date. - Connect your Google Sheets, Gmail or SMTP, OpenAI, and Slack credentials in n8n.
- Review the Switch node — confirm the safe branch terminates and the other three connect to email nodes followed by the Sheets log.
- Adjust the scoring thresholds in the Code node to match your product's typical login cadence. A daily-use tool will flag members faster than a weekly-use tool with the default 14-day cutoff.
- Run the workflow manually against a small test batch before activating. Verify the risk score, tier classification, and the OpenAI email output for one member from each non-safe tier.
- For real-time win-back, add the Stripe webhook path from Pattern 1 as a second workflow that runs independently of the daily batch.
For the freemium conversion side of your funnel — turning free users into paying ones rather than retaining existing subscribers — the n8n freemium automation guide covers the full usage-triggered upgrade pipeline. For Stripe-level subscription health monitoring including MRR tracking and trial management, see the n8n subscription management guide.
Deploy the Membership Churn Recovery Engine →Every product has at-risk accounts right now. The only question is whether they'll be contacted before or after they cancel. A daily scoring workflow catching them two weeks early is a much cheaper intervention than losing a month of MRR per account you could have saved with a single well-timed email.
Browse all n8n retention templates →Common questions
How does n8n detect at-risk subscribers before they cancel?
What behavioral signals work best for churn scoring in n8n?
Can n8n automate win-back emails for recently cancelled subscribers?
Get the workflow templates this guide is built on
Import-ready n8n JSON, step-by-step setup, and tested end-to-end. One-time payment, own it forever.
Get 3 tested n8n templates, free
The full customer package for three real catalog templates — workflow JSON, step-by-step setup guide, credential checklist. Test-run on a live n8n instance like everything we sell. Plus new templates and automation guides in your inbox. No spam, unsubscribe anytime.
- 01Smart To-Do List ManagerPre-built n8n workflow template that automates productivity with OpenAI. Live in about 10 minutes.$14
- 02Email Follow-Up AutomatorPre-built n8n workflow template that automates crm with OpenAI. Live in about 15 minutes.$12
- 03Market Trend AnalyzerPre-built n8n workflow template that automates data processing with OpenAI. Live in about 10 minutes.$14
More automation guides

Automate Sales Outreach with n8n: Enrich, Sequence, and Follow Up at Scale
Sales outreach fails at scale in a predictable way: the first email goes out, a quarter of contacts don't respond, and the follow-up never happens because no one queued it. At 50 contacts that's a mil…

n8n Telegram Automation: Alerts, Bots, and Notification Workflows
Telegram Gets Read. Email Doesn't. Most alert pipelines route to email. That's fine until the alert actually matters — a service down at 2 a.m., a high-value user hitting a plan ceiling, a negative re…

Automate Freemium Conversion with n8n Workflows
Free Users Don't Upgrade on Their Own Most SaaS products convert fewer than 5% of free signups to paid. That's not a product quality problem. It's a timing problem. Free users hit moments of genuine n…