Churn is the disease that kills most indie SaaS products. Not "customers canceled because the product was bad" — customers canceled because nobody noticed they were about to, and nobody reached out in time. The product was fine. The signal was missed.
Commercial customer-success platforms exist to catch these signals. They're priced for companies with a customer success team. For an indie SaaS with 100-2,000 customers and a founder wearing all the hats, they're not practical.
retentionradar is the indie version. One signal, one workflow, cheaper than lunch.
What It Does
- Daily at-risk list. Every night: rescore every customer. Surface the top N at-risk today with the specific signal that flipped them. Actionable, not a dashboard-to-nowhere.
- Multi-signal scoring. Usage, billing, support, product. Weighted blend configurable per business.
- Win-back campaigns. Templates: founder-style personal email, time-limited discount, feature reminder, 'did we mess up?' humility note. Route automatically based on the at-risk signal.
- Usage ingestion. Webhook endpoint accepts your product's event stream. Or pull from Stripe/Mixpanel/Amplitude. Or drop a CSV once a day.
- Cohort + trend views. Monthly churn. Reactivation rate. Campaign-level conversion.
The Scoring Model
Every customer gets a churn-risk score 0-100 updated nightly. The score combines four signal categories:
- Usage. Login frequency, feature depth, API volume. Drop in any of these relative to the customer's historical baseline adds risk.
- Billing. Failed charges, plan downgrades, subscription pauses. Any one of these is a major risk bump.
- Support. Ticket count + sentiment. Rising tickets, especially negative-sentiment ones, add risk.
- Product. Feature-flag adoption. Customers who haven't adopted the features you launched in the last 90 days are at mid-level risk.
The weights are configurable per business because they should be. A product where power users churn less has high usage weight. A product where billing friction is the #1 churn cause has high billing weight. You set weights, the model rescores, the at-risk list updates.
def compute_score(customer):
usage_z = (customer.recent_usage - customer.baseline_usage) / customer.usage_std
billing_flags = customer.failed_charges_90d + customer.downgrades_90d
support_score = customer.tickets_30d * avg_sentiment(customer.tickets_30d)
product_adoption = customer.features_adopted / features_launched_last_90d
risk = (
WEIGHT_USAGE * max(0, -usage_z) # only negative z matters
+ WEIGHT_BILLING * billing_flags
+ WEIGHT_SUPPORT * max(0, -support_score)
+ WEIGHT_PRODUCT * (1 - product_adoption)
)
return min(100, max(0, risk * 100))
The Win-Back Workflow
When a customer's score crosses a threshold you set (default: 65), the system fires a win-back action. The action depends on why the score flipped:
- Payment failure: send a "card didn't go through, here's how to fix it" email. Not a sales pitch — just a helpful nudge.
- Usage drop: personal founder email asking if something's wrong. Can be automated-but-personal ("Hey {name}, noticed you haven't been in as much. Anything I can help with?").
- Downgrade: feature-reminder email showing what they gave up + a time-limited offer to re-upgrade at the old rate.
- Support signal: humility note acknowledging the pain and offering a call with the founder.
None of this is magic — it's the playbook every good founder knows but doesn't have time to execute manually. retentionradar does the execution.
Integrations
Usage data comes in three ways:
- Webhook. Your app POSTs events to retentionradar as they happen. Low-latency, requires code changes on your end.
- API pull. Connectors for Stripe, Mixpanel, Amplitude. Nightly sync. Zero code changes.
- CSV drop. Export from whatever tool you're using, drop the CSV, parsed overnight. The 'low-tech' option.
Most founders start with #3 (CSV drop), realize it works, and graduate to #2 (API pull) when they want to automate. Few need #1 unless they have real-time churn-prevention workflows.
The Build
Flask + SQLAlchemy + Postgres (SQLite for self-host). Celery + Redis for the nightly scoring job. Templated email via Mailgun/Postmark/SendGrid (your pick). About 2,400 lines of custom Python, because the scoring and win-back logic gets intricate fast.
git clone https://github.com/Dangercorn-Enterprises/retentionradar.git
cd retentionradar
pip install -r requirements.txt
# configure .env with your DB + email provider
python app.py
# → http://localhost:8442
Pricing
- Self-host: $0. Full scoring + win-back logic. Bring your own email provider.
- Hosted Pro: $39/mo. Managed, Stripe + Mixpanel + Amplitude connectors, founder-style email templates, daily at-risk digest.
- Growth: $129/mo. Multi-client (agency mode), Slack + PagerDuty alerts, custom scoring models, SSO.
For a SaaS at 300 customers averaging $30 MRR, reducing monthly churn by even 1% is $900/month of preserved revenue. $39/month is trivial in that math.
Who It's For
Indie SaaS founders with 50-5,000 paying customers. Solo operators wearing the customer-success hat. Bootstrappers who can't justify ChurnZero pricing. Agencies managing churn for multiple client SaaS products.
The best win-back email is a human one, sent at the right time. Software shouldn't replace the human; it should tell the human when to hit send.
Related
codesnips for founders shipping developer tools. meetingmind for the founder running customer-call notes. the SiteLens retro for context on how we think about customer touchpoints.