Reference for the 15 metrics surfaced across the Finance domain: definitions, formulas, and source tables.
The four pillars that structure every card in the dashboard.
Recurring monthly revenue normalized per month, projected to a year for ARR.
Client churn counts leaving accounts; MRR churn counts lost euros. Keep them distinct.
LTV observed per cohort vs acquisition cost. > 3× healthy, < 1× alarming.
Growth + margin. A classic SaaS indicator of balance between growth and profitability.
Explore each metric catalog, design choices and data flow in detail.
Every finance metric surfaced in the UI, with formula and data source.
| Metric | Formula | Source |
|---|---|---|
MRR Monthly recurring revenue: sum of active subscriptions normalized to a month. Excludes pure trials and lifetime trials. | Σ (effective amount / 100) per active subscription | SQL: compute_mrr_daily mrr_daily.mrr |
ARR Annualized projection of MRR: straight 12-month extrapolation. Does not account for seasonality. | MRR × 12 | metrics.ts computeArr(mrr) |
ARPA Average revenue per active account. Snapshot of per-customer value. | MRR / active clients | metrics.ts computeArpa(mrr, activeClients) |
30d / 90d client churn Rolling client loss rate over 30 or 90 days. Recurring-only base when `useRecurring` is set. | clients churned (30d) / avg active clients (30d) × 100 | metrics.ts computeChurnRate(rows, { useRecurring }) |
Global churn Client loss rate across all available history. Weighted average of monthly churns (each month weighted by its active base). Long-term view. | Σ monthly churned / Σ monthly active × 100 | metrics.ts computeChurnGlobalWeighted(months) |
Trial → paid conversion Share of ended trials that became paid subscriptions within 30 days. | converted trials / ended trials × 100 | metrics.ts computeConversionRate(funnel) |
NRR On the cohort of clients active at month start (mrr_start > 0): retained MRR + expansion − contraction − churn. New clients and reactivations are excluded from both sides. Above 100% = the existing base grows on its own. | (starting + expansion_on_existing − contraction − churn) / starting × 100 | metrics.ts + SQL: gocroco_nrr_grr_monthly computeNrr({startingMrr, expansionMrr, contractionMrr, churnMrr}) |
GRR Like NRR but without expansion. Measures pure retention of the starting base (capped at 100%). | (starting − contraction − churn) / starting × 100 | metrics.ts + SQL: gocroco_nrr_grr_monthly computeGrr({startingMrr, expansionMrr, contractionMrr, churnMrr}) |
Observed LTV Realized LTV per cohort: cumulative observed MRR up to the latest tenure, divided by cohort size. No projection — only cash collected. | cumulative observed MRR / cohort size | SQL: gocroco_ltv_by_cohort computeMedianLtvObserved(rows) |
Estimated LTV LTV projection using the classic SaaS formula. Less reliable than observed LTV: explodes as churn approaches 0. Hidden when monthly churn < 0.5%. | ARPA / monthly churn | metrics.ts computeLtvEstimated(arpa, monthlyChurnPct) |
Indicators that put revenue next to cost and time-to-recoup.
| Indicator | Formula | Target | Source |
|---|---|---|---|
Rule of 40 Classic SaaS balance indicator between growth and profitability. | NRR% + MRR growth% | ≥ 40% | computeRuleOfForty(nrrPct, mrrGrowthPct) |
Magic Number Efficiency of marketing spend: new MRR generated per euro of marketing. | ΔMRR(quarter) × 4 / marketing spend(quarter) | ≥ 0.75 | computeMagicNumber(netNewMrrQuarter, marketingSpendQuarter) |
Burn Multiple Net burn vs new net MRR. Lower is better — shows capital efficiency. | net burn / net new MRR | < 2 | SQL: gocroco_unit_economics_monthly |
Loss breakdown and MRR projection — their mechanics.
Daily table feeds the Losses tab. Churn timing charts use churned_mrr grouped by the day the subscription ended. Top movers come from gocroco_finance_top_movers.
12-month projection built on the average of the last 6 months for new / churn / expansion MRR. Confidence band is a heuristic (±15% × m/horizon), not a statistical interval.
Why some metrics are computed the way they are.
Only trials that actually ended (paid or expired) are counted in the conversion ratio. Ongoing trials would artificially lower it.
Trade-off: Month-over-month numbers can be noisy when trial volume fluctuates.
Monthly churn rates are averaged, each month weighted by its active client base. Simple averaging would overweight small early months.
Trade-off: Newer months have less influence when the business grew fast.
Estimated LTV (ARPA / churn) explodes as churn → 0. We show observed LTV from realized cohorts whenever available.
Trade-off: Observed LTV needs mature cohorts; early-stage cohorts show little data.
MRR uses the effective amount billed per subscription, not the list price. Discounts, credits, and one-shot offsets are respected.
Trade-off: Requires regular Stripe sync to stay fresh.
Founders paid in 12×, lifetime deals paid in tranches, etc. are counted in total MRR but excluded from recurring. Goals align on recurring.
Trade-off: Total MRR and recurring MRR can diverge — pay attention to which one you read.
Not end-of-period count. Smooths out month-boundary churn spikes.
Trade-off: Slightly underestimates churn during rapid growth.
A location joins a cohort the first month it becomes a paying subscriber. Not the trial start, not the signup.
Trade-off: Locations that pause and resume skew to a single cohort.
A subscription scheduled to cancel at the end of the period is still active today — kept in MRR until the actual end date.
Trade-off: Inflates MRR briefly before the scheduled end date.
Accounts with MRR ≤ €2 are treated as sandboxes and excluded from most metrics. Toggleable per dashboard.
Trade-off: A real micro-plan would be excluded by accident.
The journey of a finance metric, end to end.
stripeSync.ts keeps stripe_subscriptions up to date with full history (one row per subscription event). stripe_subscription_current view exposes the latest row per location.
compute_mrr_daily snapshots recurring and total MRR per location per day, applying overrides from subscription_overrides.
Aggregate per-day MRR, new_mrr, expansion, contraction, churned_mrr across all active clients. Source of Pilotage and Losses charts.
location_cohort_monthly tracks per-cohort starting / expansion / churn / contraction MRR every month. Feeds NRR, GRR, LTV.
Pages under app/finance/* call the matching RPC (gocroco_finance_dashboard, gocroco_nrr_grr_monthly, gocroco_cac_monthly, etc.) and render the results with Recharts + MetricCard.
Background jobs that feed the finance domain.
The full finance stack relies on compute_mrr_daily having run for the target day. It runs nightly (mrr_daily_compute_0200) and fills any missing day automatically.
On top of that, Stripe webhooks stream events into stripe_subscriptions in near real-time. A reconciliation job runs hourly to catch any missed event.
If a day looks off, SELECT public.compute_mrr_daily('YYYY-MM-DD') re-snapshots it. audit:reliability includes a reconcile-MRR check.
Short answers to the questions we get most often.
Stripe MRR includes one-shots; we split recurring vs one-shot. Also, we respect subscription_overrides (founder deals, excluded amounts) which Stripe doesn't know about.
Expansion on existing accounts can more than compensate for churn on the same cohort. That's the whole point of NRR.
The formula ARPA / churn explodes when monthly churn < 0.5%. We hide the value in that range to avoid misleading numbers.
CAC requires manually entered marketing + sales spend. Enter the spend on /finance/acquisition to populate it.
A cohort's retention appears only after the corresponding month has elapsed. Empty cells are future months.
Client churn counts accounts; MRR churn counts euros. One big leaving client can push MRR churn high while client churn stays low.
Find the row in /finance/clients, open the drawer to see its history, and compare with Stripe. subscription_overrides can hide a custom deal.
Source files to dig into further.
lib/analytics/finance/metrics.tslib/analytics/finance/glossary.ts + finance.glossary namespacelib/stripeEffectiveAmount.tsapp/finance/pertes/_components/losses-timeline-chart.tsxapp/finance/forecast/ + gocroco_mrr_forecastscripts/audit/run-reliability-audit.ts