# Churn figures

**Summary:** Churn shows recorded subscription losses as a percentage of active subscriptions, using the latest saved count in the same period.

- Role: [Technical Support](https://www.subrite.no/technical-support)
- Source: https://www.subrite.no/technical-support/insights-churns
- Updated: 2026-09-28
- Markdown index: https://www.subrite.no/technical-support/llms.txt

The calculation does not use the opening subscriber base or count unique lost people.

<a id="numerator-and-denominator"></a>
## Numerator and denominator

Gross losses = `deactivations + expirations + stops`. Net losses subtract `reactivations`; new sales and routine renewals do not offset losses.

These fields come from daily subscription-history summaries. Deactivation includes `ACTIVE` changing to `PAUSED` or `INACTIVE`; expiration requires an active subscription. A stopped event can follow a paused status. One subscription can therefore contribute more than one loss event. [Source: loss aggregation](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/repositories/subscription-activity-summary.repository.ts#L225-L232).

The denominator selects the latest `subscription_summary.createdAt` for each group and period, then sums quantities at that timestamp. The writer counts `ACTIVE` subscriptions. It groups stored rows by plan, package, provider, introductory-period flag and automatic renewal. [Sources: active-count writer](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/services/stats-store.service.ts#L111-L179), [snapshot selection](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/repositories/subscription-summary.repository.ts#L70-L157).

The calculation matches loss and denominator rows by year, period and group ID. Fetching 13 denominator periods does not mean the previous period supplies the base.

Rate = `max(losses / active count × 100, 0)`, calculated only when the base is positive. There is no upper clamp. `additionalData` retains the raw loss count, including negative net losses. [Source: rate calculation](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/services/stats.services.ts#L943-L971).

<a id="paid-and-free-classification"></a>
## Paid and free classification

The same `subscriptionType` filter applies to numerator and denominator. **Paid** means positive base-plan price; **Free** means zero. It does not test whether a payment succeeded.

Base-plan price sums plan-product prices only for published, nonoptional products. The loss table has no price, so it joins the latest plan-price snapshot in the same period.

A missing price resolves through `COALESCE(price, 1)`, classifying that loss as paid. This can retain a loss after the plan has no remaining active subscriptions. [Source: loss price mapping](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/repositories/subscription-activity-summary.repository.ts#L171-L203).

<a id="dates-groups-and-total"></a>
## Dates, groups and Total

Losses are grouped by summary `createdAt`. [New and stopped](https://www.subrite.no/technical-support/insights-new-and-stopped?md=true) instead groups by `dateOfRecord`. A summary written after a month boundary can place the same events in different report months.

The page sends `subscriptionType`, `type`, `groupBy` and `noOfLine`; it exposes no period or range control. The API defaults to monthly and the formatter returns the latest 12 buckets, including the unfinished current month. [Sources: page request](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/frontend/src/app/%28admin%29/admin/%28panel%29/analytics/statistics/churns/page.tsx#L49-L70), [defaults](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/dto/historical-churn-rate-req.dto.ts#L17-L67).

Details selects the highest-rate groups in the latest period containing rates. **All** means at most 100 groups; `ignoreOthers=true` prevents an Others series. Older groups outside that selection can disappear.

Total is calculated separately from all queried groups: summed losses divided by summed active counts. It is not the mean of visible rates, and hiding detail lines does not change it.

For example, 10/100 and 10/1,000 give group rates of 10% and 1%. Total is 20/1,100 = 1.82%, not 5.5%. [Source: separate details and total calculation](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/services/stats.services.ts#L703-L760).

<a id="diagnose-missing-or-unexpected-rates"></a>
## Diagnose missing or unexpected rates

- Missing point: check whether the matching denominator exists and exceeds zero. Losses can exist without a calculated rate.
- Negative net loss: the API clamps the rate to zero, and the chart converts zero to `null`. No point is plotted.
- Rate above 100%: compare event counts with the same-period active base. Repeated events and a smaller remaining base can exceed 100%.
- Unexpected **qty**: inspect `additionalData`. Zero becomes an empty tooltip string; nonzero values supply the loss count.
- Detail and Total disagree: compare summed losses and bases, not an average of lines. Total also includes groups omitted from Details.
- Total disappears after hiding lines: restore every legend group; the shared chart reuses positional visibility identifiers.

The chart supplies a separately calculated Total tooltip override. [Source: rendering and tooltip data](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/frontend/src/app/%28admin%29/admin/%28panel%29/analytics/statistics/churns/ChurnStats/index.tsx#L36-L131).

`historical-churn-rates` requires Dashboard read permission; menu access also depends on Analytics access and Insights. [Source: endpoint gate](https://github.com/subrite/subrite-crm/blob/6cd1850569be3b1702ca736a19320c7626efb7bc/api-server/src/modules/stats/controllers/stats.controller.ts#L361-L370).

<a id="sources-and-verification"></a>
## Sources and verification

Source checked 28 September 2026 at `6cd1850569be3b1702ca736a19320c7626efb7bc`. Prior UI evidence confirms the selectors and Net churn selection. No fresh UI, numeric reconciliation, tooltip-edge or ordinary-role test was performed.

For graph interpretation and controls, see [Churn figures](https://www.subrite.no/administrators/insights-churns?md=true).

## Related pages

- [Churn figures](https://www.subrite.no/administrators/insights-churns?md=true): Churn shows recorded subscription losses as a percentage of active subscriptions, using the latest saved count in the same period.
