Lester Leong
How to Calculate Churn Rate for SaaS (And the 3 Ways Teams Get It Wrong)
The Number Everyone Calculates, Almost Nobody Calculates Correctly
Churn rate should be the easiest metric in your analytics stack. Customers who left divided by customers you started with. Done.
Except it never is. Across 20+ consulting engagements at Gradient Growth, I have reviewed churn calculations at SaaS startups, B2B platforms, and consumer subscription businesses. Roughly two-thirds of them had a material error in how they computed churn. Not a rounding difference. An error that changed the number by 20% or more, which cascaded into broken LTV models, misleading board decks, and marketing spend allocated against phantom unit economics.
At a financial social media startup I worked at before its acquisition, churn was the single most scrutinized metric during diligence. The acquirer's team pulled our numbers apart for weeks. Every denominator choice, every cohort boundary, every definition of "active" was challenged. That experience taught me that the way you calculate churn matters as much as the number itself. A clean methodology survives diligence. A sloppy one creates doubt about everything else in your data room.
Now, working on a GenAI squad at a major finance technology company, I see churn at a scale where a 0.1% miscalculation translates into millions of dollars in misattributed revenue. The discipline required at that scale has made me allergic to shortcut churn formulas.
Here is the formula, the three mistakes that corrupt it, and a Python implementation that handles the edge cases most teams ignore.
The Core Formulas
Simple (logo) churn rate:
Churn Rate = Customers Lost During Period / Customers at Start of Period
If you started March with 500 customers and 35 cancelled, your monthly churn rate is 35 / 500 = 7.0%.
This is logo churn. It counts customers as equal regardless of what they pay. A $29/month startup and a $2,900/month enterprise contract each count as one.
Revenue churn rate:
Revenue Churn = MRR Lost from Churned + Downgraded Customers / MRR at Start of Period
If you started March with $100,000 MRR and lost $8,500 from cancellations and downgrades, your gross revenue churn is 8.5%.
Net revenue churn (the metric that actually matters for growth):
Net Revenue Churn = (MRR Lost from Churn + Downgrades - MRR Gained from Expansions) / MRR at Start of Period
If that same $100,000 MRR business lost $8,500 but gained $11,200 from existing customers upgrading or adding seats, your net revenue churn is ($8,500 - $11,200) / $100,000 = -2.7%. Negative net churn means your existing customer base is growing without any new sales. This is the engine behind the best SaaS companies in the world.
I wrote about [how churn feeds into LTV calculations](/insights/customer-ltv-calculation-startups) in a separate article. Get the churn number wrong, and LTV inherits the error with a multiplier.
Mistake 1: Wrong Denominator
This is the most common error I find. It looks innocent and it is not.
The question: when a customer signs up mid-month and churns before month-end, do they appear in your denominator? What about customers who signed up on the last day of the period?
One consulting client (a B2B SaaS platform, roughly $2M ARR) was calculating churn using end-of-period customer count as the denominator. Their formula was: churned customers / customers at end of month. Because the denominator already excluded the churned customers, the number was systematically understated. Their reported churn was 4.2%. The actual figure, using beginning-of-period count, was 5.8%. That 1.6-point gap made their LTV look 38% higher than reality.
The correct denominator is always the customer count at the start of the period. Some teams use the average of start and end counts to account for mid-period additions, which is defensible for businesses with high intra-period signup volume. But start-of-period is the cleaner default, and it is what most investors expect to see.
For businesses with significant mid-period customer additions, a weighted average denominator prevents new signups from artificially deflating the rate:
Adjusted Denominator = Starting Customers + (New Customers x Fraction of Period Remaining)
If you added 40 customers evenly throughout a 30-day month, the average new customer had 15 days of exposure. Your adjusted denominator is 500 + (40 x 0.5) = 520 instead of 500 or 540.
Mistake 2: Blending Voluntary and Involuntary Churn
Not all churn has the same cause, and treating it as a single number hides the information you need to fix it.
Voluntary churn is a customer deciding to leave. They cancelled because the product did not deliver value, a competitor offered something better, their budget got cut, or they simply no longer need what you sell. This is a product and retention problem.
Involuntary churn is a customer whose payment failed. Their credit card expired, the charge was flagged as fraud, or their billing address changed. The customer did not decide to leave. Their payment method failed and nobody recovered it. This is an operations problem.
At the financial social media startup, we separated these two streams early and it changed how we prioritized engineering work. Involuntary churn was running at 1.8% monthly. After implementing a dunning email sequence (three retries over 10 days, with an in-app notification on day 7), involuntary churn dropped to 0.6%. That single operational fix was equivalent to a 1.2-point improvement in total churn, which would have taken months of product work to achieve through voluntary retention improvements.
From my consulting work, involuntary churn typically accounts for 20-40% of total churn at SaaS companies that have not implemented proper dunning. That means a significant portion of reported churn is recoverable with a billing retry sequence and a couple of transactional emails.
If you are reporting a single blended churn number, you are missing the cheapest improvement opportunity in your business.
Mistake 3: Ignoring Expansion Revenue in Net Churn
Gross churn tells you how much revenue walked out the door. Net churn tells you whether your existing customer base is growing or shrinking. The distinction is critical, and most early-stage startups only track gross churn because they do not have expansion revenue yet.
The problem comes later. Once you introduce upsells, seat-based pricing, or usage-based components, gross churn alone gives an incomplete picture. A company with 8% gross revenue churn and 12% expansion revenue has negative net churn. That is a fundamentally different business from one with 8% gross churn and 2% expansion, even though the gross number is identical.
I worked with a vertical SaaS company (workforce management, roughly 400 customers) that was reporting 6.5% monthly revenue churn to their board. When we decomposed the number, gross churn was 6.5% but expansion from existing customers was running at 4.1%. Their net churn was 2.4%. The board had been in "fix churn" mode for two quarters based on a number that overstated the severity by nearly 3x. Once we reframed the conversation around net churn, the strategic priority shifted from pure retention to accelerating expansion within the retained base, which was a much higher-ROI initiative.
Track both. Report both. Make decisions on net churn. Diagnose problems with gross churn.
Churn Benchmarks by Business Type
These are ranges I have observed across consulting engagements, not industry surveys. They reflect what I have actually measured in real companies.
| Business Type | Monthly Logo Churn | Monthly Revenue Churn (Gross) | Annual Logo Churn | |---|---|---|---| | B2B SaaS (SMB) | 3-7% | 4-8% | 30-60% | | B2B SaaS (Mid-Market) | 1.5-3% | 2-4% | 15-30% | | B2B SaaS (Enterprise) | 0.5-1.5% | 0.5-2% | 5-15% | | Consumer Subscription | 5-10% | 5-12% | 45-70% | | Usage-Based / PLG | 3-6% | Highly variable | 30-50% |
Ranges based on 20+ consulting engagements across SaaS, consumer, and marketplace businesses.
Two patterns worth noting. First, revenue churn is almost always higher than logo churn in SMB-heavy businesses because smaller customers churn at higher rates but the surviving ones do not expand enough to offset it. Second, enterprise churn looks low on a monthly basis but compounds meaningfully over a year. A 1% monthly churn rate means you lose 11.4% of your customer base annually, not 12%. The compounding works in your favor here.
The annual relationship: Annual Churn = 1 - (1 - Monthly Churn)^12.
Python: A Churn Calculator That Handles the Edge Cases
This implementation handles the three mistakes above: correct denominator with mid-period adjustment, voluntary/involuntary segmentation, and net revenue churn.
```python from dataclasses import dataclass from typing import Optional
@dataclass class ChurnResult: logo_churn_rate: float gross_revenue_churn_rate: float net_revenue_churn_rate: float voluntary_churn_rate: float involuntary_churn_rate: float annualized_logo_churn: float customers_start: int customers_end: int mrr_start: float mrr_end: float
def calculate_churn( customers_start: int, customers_churned_voluntary: int, customers_churned_involuntary: int, customers_added: int, mrr_start: float, mrr_lost_churn: float, mrr_lost_downgrade: float, mrr_gained_expansion: float, period_days: int = 30, avg_days_before_new_customer_churns: Optional[float] = None, ) -> ChurnResult: """ Calculate churn rates with correct denominator handling, voluntary/involuntary segmentation, and net revenue churn.
Args: customers_start: Customers at the beginning of the period. customers_churned_voluntary: Customers who actively cancelled. customers_churned_involuntary: Customers lost to payment failure. customers_added: New customers acquired during the period. mrr_start: Monthly recurring revenue at period start. mrr_lost_churn: MRR lost from customers who fully cancelled. mrr_lost_downgrade: MRR lost from customers who downgraded. mrr_gained_expansion: MRR gained from existing customer upgrades. period_days: Length of the period in days. avg_days_before_new_customer_churns: If set, adjusts the denominator for mid-period additions using exposure weighting. """ total_churned = customers_churned_voluntary + customers_churned_involuntary
# Denominator: start-of-period count, optionally adjusted # for mid-period additions to prevent artificial deflation. if avg_days_before_new_customer_churns is not None: exposure_fraction = ( (period_days - avg_days_before_new_customer_churns) / period_days ) denominator = customers_start + customers_added * max(0, exposure_fraction) else: denominator = customers_start
if denominator == 0: raise ValueError("Cannot calculate churn with zero customers.")
# Logo churn logo_churn = total_churned / denominator
# Voluntary vs involuntary voluntary_rate = customers_churned_voluntary / denominator involuntary_rate = customers_churned_involuntary / denominator
# Revenue churn if mrr_start == 0: raise ValueError("Cannot calculate revenue churn with zero MRR.")
gross_rev_churn = (mrr_lost_churn + mrr_lost_downgrade) / mrr_start net_rev_churn = ( (mrr_lost_churn + mrr_lost_downgrade - mrr_gained_expansion) / mrr_start )
# Annualized (compounded) annualized = 1 - (1 - logo_churn) ** 12
customers_end = customers_start + customers_added - total_churned mrr_end = mrr_start - mrr_lost_churn - mrr_lost_downgrade + mrr_gained_expansion
return ChurnResult( logo_churn_rate=round(logo_churn, 4), gross_revenue_churn_rate=round(gross_rev_churn, 4), net_revenue_churn_rate=round(net_rev_churn, 4), voluntary_churn_rate=round(voluntary_rate, 4), involuntary_churn_rate=round(involuntary_rate, 4), annualized_logo_churn=round(annualized, 4), customers_start=customers_start, customers_end=customers_end, mrr_start=mrr_start, mrr_end=round(mrr_end, 2), )
# Example: mid-market SaaS with 500 customers, $200K MRR result = calculate_churn( customers_start=500, customers_churned_voluntary=22, customers_churned_involuntary=13, customers_added=40, mrr_start=200_000, mrr_lost_churn=14_200, mrr_lost_downgrade=3_800, mrr_gained_expansion=11_500, period_days=30, avg_days_before_new_customer_churns=15, )
print(f"Logo churn: {result.logo_churn_rate:.1%}") print(f" Voluntary: {result.voluntary_churn_rate:.1%}") print(f" Involuntary: {result.involuntary_churn_rate:.1%}") print(f"Gross revenue churn: {result.gross_revenue_churn_rate:.1%}") print(f"Net revenue churn: {result.net_revenue_churn_rate:.1%}") print(f"Annualized logo: {result.annualized_logo_churn:.1%}") print(f"MRR end: ${result.mrr_end:,.0f}") ```
The output for this example: 6.7% logo churn (4.2% voluntary, 2.5% involuntary), 9.0% gross revenue churn, 3.3% net revenue churn, 56.0% annualized logo churn. The gap between gross and net revenue churn immediately tells you that expansion revenue is partially offsetting losses, but not enough to achieve negative net churn.
Reading the Results: What the Numbers Tell You
The churn number is a diagnostic tool, not a scorecard. When I work with teams on churn, the first question is never "how do we reduce the number." It is "where is the number coming from."
Three diagnostic questions, in order:
1. What fraction is involuntary? If involuntary churn is more than 30% of total churn, fix billing before touching the product. Dunning sequences, card updater services (Visa Account Updater, Mastercard ABU), and pre-expiry reminders typically recover 30-50% of involuntary churn within the first month of implementation.
2. Is revenue churn higher or lower than logo churn? If revenue churn is significantly higher, your largest customers are leaving. That is an entirely different problem than losing a high volume of small accounts. One consulting client discovered that their logo churn was 4% but revenue churn was 9% because two enterprise accounts had downgraded. The fix was a dedicated account management process for their top 20 customers, not a broad retention campaign.
3. What does net churn look like by cohort? Blended net churn can mask deterioration in recent cohorts. If your 2025 cohorts have 2% net churn but your 2026 cohorts are running at 5%, something changed. Pricing, onboarding, competitive pressure, customer mix. The flip side of churn is [retention curve analysis](/insights/retention-curve-analysis-guide), and the cohort-level view is where the two analyses connect.
The Compounding Math That Should Keep You Up at Night
A 5% monthly churn rate does not mean you lose 60% of customers per year. It means you lose 46% (because each month's denominator is smaller than the last). But that still means you need to acquire nearly as many customers as you currently have just to stay flat.
At 5% monthly churn, you need to grow your customer base by 82% annually just to achieve 0% net customer growth. That is an acquisition treadmill. Every point of churn reduction has a compounding benefit that makes acquisition more efficient. Reducing monthly churn from 5% to 3% cuts the annual replacement rate from 46% to 31%. That is 15 points of your customer base you no longer need to re-acquire every year.
This is why I tell every SaaS founder the same thing: the ROI on a 1-point churn reduction almost always exceeds the ROI on a 10% improvement in top-of-funnel conversion. Acquisition is linear. Retention is exponential.
Get the Methodology Right First
Most churn conversations start with "our churn is too high" and immediately jump to solutions. Better onboarding. More engagement emails. Feature improvements. Customer success hires.
Those might all be the right moves. But if the number itself is miscalculated, you are solving the wrong problem at the wrong magnitude. Fix the denominator. Separate voluntary from involuntary. Track net revenue churn alongside gross. Then, and only then, start diagnosing causes.
The formula is simple. The discipline to calculate it correctly, decompose it into actionable segments, and track it consistently across cohorts is what separates teams that actually reduce churn from teams that just talk about it.
---
I help SaaS teams build churn diagnostics that surface the real problem, not just the number. [lester@gradientgrowth.com](mailto:lester@gradientgrowth.com)