Churn¶
Logo churn and revenue churn from the Tidemill engine.
How churn is measured¶
Logo (customer) churn — the fraction of customers who fully cancel:
logo_churn = customers_fully_churned / customers_active_at_period_start
A customer is "active at start" if they had positive MRR at the period start (cumulative MRR movements before start > 0). They are "fully churned" if, by the period end, they have zero active subscriptions remaining.
Revenue churn — the fraction of MRR lost to cancellations:
revenue_churn = |churned_MRR| / starting_MRR
churned_MRR sums the MRR of every subscription whose churn event
falls within [start, end] (closed-closed — both endpoints inclusive,
see docs/definitions.md).
from tidemill import reports
from tidemill.reports.client import TidemillClient
reports.setup()
START, END = "2025-07-01", "2026-04-30"
CHURN_START, CHURN_END = "2025-11-01", "2025-11-30"
tm = TidemillClient()
1. Customer churn sets¶
C_start — customers active at period start (positive MRR). C_churned — subset of C_start who fully churned during the window.
detail = reports.churn.customer_detail(tm, CHURN_START, CHURN_END)
reports.churn.style_c_start(detail)
| customer | customer_name | starting_mrr |
|---|---|---|
| cus_ULeOmo28L85BDt | Active Starter #1 | $20.00 |
| cus_ULeP0p3hQP4tXH | Churned Pro #11 | $79.00 |
| cus_ULeP2nHUy4PfEW | Active Annual Pro #6 | $65.83 |
| cus_ULeP4MdsGIqA3N | Active Annual Enterprise #7 | $207.50 |
| cus_ULePFJs2l5ftYr | Upgraded Starter→Pro #12 | $20.00 |
| cus_ULePUoQI3jKcEM | Active Starter Heavy #3 | $20.00 |
| cus_ULePYzNMidnEnZ | Active Starter #2 | $20.00 |
| cus_ULePZEpGaYDqub | Active Monthly Pro #5 | $79.00 |
| cus_ULePdAg7TfFaRx | Active Monthly Pro #4 | $79.00 |
| cus_ULePffUmdz4BT2 | Late Churned Starter #13 | $20.00 |
| cus_ULePlU5uLDHBFQ | Downgraded Pro→Starter #10 | $20.00 |
| cus_ULePzVuCb6JBeL | Upgraded Starter→Pro #9 | $79.00 |
| cus_ULeQWLfzuwfTyC | Trial Jul →convert #20 | $20.00 |
| cus_ULeQWt3mB3sUz4 | Trial→Active Starter #18 | $20.00 |
| cus_ULeQX6MBPeb0ao | Churn→Reactivate Starter #15 | $20.00 |
| cus_ULeQhHVGpDylFL | Late Downgraded Pro→Starter #14 | $79.00 |
| cus_ULeRrPC40IFaif | Trial Aug →convert #24 | $20.00 |
| cus_ULeS0TRSWVhFuj | Trial Aug →convert #26 | $20.00 |
| cus_ULeSo3PeqwKWzM | Trial Aug →convert #25 | $20.00 |
| cus_ULeTVlnGI3M9eb | Trial Sep →convert #29 | $20.00 |
| cus_ULeTzx7snOUDxd | Trial Sep →convert #28 | $20.00 |
| cus_ULeV4oJlMp1f7y | Trial Oct →convert #33 | $20.00 |
| cus_ULeVAcwU6VJHz0 | Trial Oct →churn #35 | $20.00 |
| cus_ULeVNwHMuukNRg | Trial Oct →churn #34 | $20.00 |
| cus_ULeVXcQjzR9s20 | Trial Oct →convert #32 | $20.00 |
| TOTAL | $1,028.33 |
reports.churn.style_c_churned(detail)
| customer | customer_name | starting_mrr | churned_mrr |
|---|---|---|---|
| cus_ULeP0p3hQP4tXH | Churned Pro #11 | $79.00 | $79.00 |
| cus_ULeVAcwU6VJHz0 | Trial Oct →churn #35 | $20.00 | $20.00 |
| cus_ULeVNwHMuukNRg | Trial Oct →churn #34 | $20.00 | $20.00 |
| TOTAL | $119.00 | $119.00 |
2. Churn Rates¶
Logo and revenue churn from the Tidemill API. These should match the C_start / C_churned sets above:
- Logo churn = |C_churned| / |C_start|
- Revenue churn = sum(churned MRR) / sum(starting MRR)
reports.churn.style_snapshot(reports.churn.snapshot(tm, CHURN_START, CHURN_END, detail=detail))
| Metric | Numerator | Denominator | Rate |
|---|---|---|---|
| Logo churn | 3 customers | 25 customers | 12.0% |
| Revenue churn | $119.00 | $1,028.33 | 12.0% |
Revenue churn detail¶
Every customer from C_start with their starting MRR and churned MRR. Customers who cancelled one subscription but kept another appear here with churned MRR > 0 even though they are not in C_churned.
reports.churn.style_revenue_events(
reports.churn.revenue_events(tm, CHURN_START, CHURN_END, detail=detail)
)
| customer | customer_name | starting_mrr | churned_mrr | fully_churned |
|---|---|---|---|---|
| cus_ULeOmo28L85BDt | Active Starter #1 | $20.00 | $0.00 | False |
| cus_ULeP0p3hQP4tXH | Churned Pro #11 | $79.00 | $79.00 | True |
| cus_ULeP2nHUy4PfEW | Active Annual Pro #6 | $65.83 | $0.00 | False |
| cus_ULeP4MdsGIqA3N | Active Annual Enterprise #7 | $207.50 | $0.00 | False |
| cus_ULePFJs2l5ftYr | Upgraded Starter→Pro #12 | $20.00 | $0.00 | False |
| cus_ULePUoQI3jKcEM | Active Starter Heavy #3 | $20.00 | $0.00 | False |
| cus_ULePYzNMidnEnZ | Active Starter #2 | $20.00 | $0.00 | False |
| cus_ULePZEpGaYDqub | Active Monthly Pro #5 | $79.00 | $0.00 | False |
| cus_ULePdAg7TfFaRx | Active Monthly Pro #4 | $79.00 | $0.00 | False |
| cus_ULePffUmdz4BT2 | Late Churned Starter #13 | $20.00 | $0.00 | False |
| cus_ULePlU5uLDHBFQ | Downgraded Pro→Starter #10 | $20.00 | $0.00 | False |
| cus_ULePzVuCb6JBeL | Upgraded Starter→Pro #9 | $79.00 | $0.00 | False |
| cus_ULeQWLfzuwfTyC | Trial Jul →convert #20 | $20.00 | $0.00 | False |
| cus_ULeQWt3mB3sUz4 | Trial→Active Starter #18 | $20.00 | $0.00 | False |
| cus_ULeQX6MBPeb0ao | Churn→Reactivate Starter #15 | $20.00 | $0.00 | False |
| cus_ULeQhHVGpDylFL | Late Downgraded Pro→Starter #14 | $79.00 | $0.00 | False |
| cus_ULeRrPC40IFaif | Trial Aug →convert #24 | $20.00 | $0.00 | False |
| cus_ULeS0TRSWVhFuj | Trial Aug →convert #26 | $20.00 | $0.00 | False |
| cus_ULeSo3PeqwKWzM | Trial Aug →convert #25 | $20.00 | $0.00 | False |
| cus_ULeTVlnGI3M9eb | Trial Sep →convert #29 | $20.00 | $0.00 | False |
| cus_ULeTzx7snOUDxd | Trial Sep →convert #28 | $20.00 | $0.00 | False |
| cus_ULeV4oJlMp1f7y | Trial Oct →convert #33 | $20.00 | $0.00 | False |
| cus_ULeVAcwU6VJHz0 | Trial Oct →churn #35 | $20.00 | $20.00 | True |
| cus_ULeVNwHMuukNRg | Trial Oct →churn #34 | $20.00 | $20.00 | True |
| cus_ULeVXcQjzR9s20 | Trial Oct →convert #32 | $20.00 | $0.00 | False |
| TOTAL | $1,028.33 | $119.00 |
3. Monthly Churn Rate Timeline¶
Compute logo and revenue churn rates per month to visualize churn trends over time.
churn_df = reports.churn.timeline(tm, START, END)
reports.churn.style_timeline(churn_df)
| logo_churn | revenue_churn | |
|---|---|---|
| month | ||
| Jul 2025 | nan% | nan% |
| Aug 2025 | 19.0% | 8.3% |
| Sep 2025 | 14.3% | 11.6% |
| Oct 2025 | 11.1% | 4.7% |
| Nov 2025 | 12.0% | 12.0% |
| Dec 2025 | 4.3% | 2.1% |
| Jan 2026 | 17.2% | 9.4% |
| Feb 2026 | 6.9% | 3.7% |
| Mar 2026 | 0.0% | 0.0% |
| Apr 2026 | 0.0% | 0.0% |
reports.churn.plot_timeline(churn_df)
4. Monthly Churned MRR¶
Lost MRR per month from the MRR waterfall — shows the dollar impact of churn over time.
reports.churn.plot_monthly_lost_mrr(reports.churn.monthly_lost_mrr(tm, START, END))