SaaS Metrics and Benchmarks in 2026: ARR, NRR, CAC/LTV, and Rule of 40
Master SaaS metrics: ARR/MRR calculation, NRR targets by stage, CAC/LTV ratios, Rule of 40, churn benchmarks, and the SQL queries to track them accurately.
SaaS Metrics and Benchmarks in 2026: ARR, NRR, CAC/LTV, and Rule of 40
SaaS metrics are a language. When a VC asks "what's your NRR?" they're asking whether your existing customers are growing faster than they're churning. When they ask about Rule of 40, they're asking whether your growth rate compensates for your burn. Getting these numbers wrong in a pitch destroys credibility; getting them right signals you understand your business.
This post covers the core SaaS metrics: how they're defined, how to calculate them accurately in SQL, what good looks like by stage, and the common mistakes that make boards distrust your numbers.
The SaaS Metrics Hierarchy
Revenue Metrics Health Metrics Efficiency Metrics
โโโ ARR / MRR โโโ NRR / NDR โโโ CAC
โโโ New ARR โโโ Gross Churn โโโ LTV
โโโ Expansion ARR โโโ Net Churn โโโ CAC:LTV Ratio
โโโ Churned ARR โโโ Logo Churn โโโ CAC Payback Period
โโโ Contracted ARR โโโ Revenue Churn โโโ Rule of 40
ARR and MRR: Getting the Definitions Right
MRR (Monthly Recurring Revenue) = sum of all recurring subscription revenue normalized to monthly.
ARR (Annual Recurring Revenue) = MRR ร 12.
-- MRR as of a specific date
-- This query handles prorated amounts, trial periods, and cancellations
WITH active_subscriptions AS (
SELECT
s.id,
s.customer_id,
s.mrr_amount, -- Already normalized to monthly
s.started_at,
s.cancelled_at,
s.status
FROM subscriptions s
WHERE s.status = 'active'
OR (s.status = 'cancelled' AND s.cancelled_at > :as_of_date)
)
SELECT
sum(mrr_amount) AS mrr,
sum(mrr_amount) * 12 AS arr,
count(*) AS active_subscription_count,
count(DISTINCT customer_id) AS paying_customer_count
FROM active_subscriptions
WHERE started_at <= :as_of_date;
-- Monthly MRR movement table (for waterfall chart)
SELECT
date_trunc('month', event_date) AS month,
sum(CASE WHEN event_type = 'new' THEN mrr_delta ELSE 0 END) AS new_mrr,
sum(CASE WHEN event_type = 'expansion' THEN mrr_delta ELSE 0 END) AS expansion_mrr,
sum(CASE WHEN event_type = 'contraction' THEN mrr_delta ELSE 0 END) AS contraction_mrr,
sum(CASE WHEN event_type = 'churn' THEN mrr_delta ELSE 0 END) AS churned_mrr,
sum(mrr_delta) AS net_new_mrr
FROM subscription_events
WHERE event_date >= now() - interval '12 months'
GROUP BY 1
ORDER BY 1;
MRR Event Types
-- Track every MRR-affecting event
CREATE TABLE subscription_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID NOT NULL,
sub_id UUID NOT NULL REFERENCES subscriptions(id),
event_type TEXT NOT NULL CHECK (event_type IN (
'new', -- First subscription
'expansion', -- Upgrade or seat addition
'contraction', -- Downgrade or seat reduction
'churn', -- Cancellation
'reactivation' -- Churned customer returns
)),
mrr_before NUMERIC(12,2) NOT NULL,
mrr_after NUMERIC(12,2) NOT NULL,
mrr_delta NUMERIC(12,2) GENERATED ALWAYS AS (mrr_after - mrr_before) STORED,
event_date DATE NOT NULL DEFAULT CURRENT_DATE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
๐ SaaS MVP in 8 Weeks โ Seriously
We have launched 50+ SaaS platforms. Multi-tenant architecture, Stripe billing, auth, role-based access, and cloud deployment โ all handled by one senior team.
- Week 1โ2: Architecture design + wireframes
- Week 3โ6: Core features built + tested
- Week 7โ8: Launch-ready on AWS/Vercel with CI/CD
- Post-launch: Maintenance plans from month 3
Net Revenue Retention (NRR)
NRR measures whether your existing customer base is growing. It's the single most important indicator of product-market fit and long-term business health.
Formula: NRR = (Starting MRR + Expansion - Contraction - Churn) / Starting MRR ร 100
-- NRR for trailing 12 months
WITH cohort AS (
-- Customers active at start of period
SELECT customer_id, sum(mrr_amount) AS starting_mrr
FROM subscriptions
WHERE status = 'active'
AND started_at <= now() - interval '12 months'
GROUP BY customer_id
),
current AS (
-- What those same customers pay today
SELECT s.customer_id, sum(s.mrr_amount) AS current_mrr
FROM subscriptions s
JOIN cohort c ON c.customer_id = s.customer_id
WHERE s.status = 'active'
GROUP BY s.customer_id
)
SELECT
sum(cohort.starting_mrr) AS starting_mrr,
sum(COALESCE(current.current_mrr, 0)) AS current_mrr,
round(
sum(COALESCE(current.current_mrr, 0)) /
NULLIF(sum(cohort.starting_mrr), 0) * 100, 1
) AS nrr_pct
FROM cohort
LEFT JOIN current USING (customer_id);
NRR Benchmarks by Stage
| Stage | Weak | Good | Best-in-Class |
|---|---|---|---|
| Seed / Pre-PMF | <80% | 80โ95% | >100% |
| Series A / PMF | <90% | 100โ110% | >120% |
| Series B+ | <100% | 110โ120% | >130% |
| Public SMB SaaS | <100% | 100โ110% | >120% |
| Public Enterprise SaaS | <110% | 120โ130% | >140% |
NRR >100% = growth even if you stop acquiring new customers ("negative churn"). This is what makes SaaS exponential.
Customer Acquisition Cost (CAC)
-- Blended CAC: total sales + marketing spend / new customers acquired
-- Run per quarter
WITH quarterly_spend AS (
SELECT
date_trunc('quarter', period_date) AS quarter,
sum(amount) AS total_spend
FROM marketing_spend
WHERE category IN ('ads', 'content', 'events', 'sales_salaries', 'tools')
GROUP BY 1
),
quarterly_new_customers AS (
SELECT
date_trunc('quarter', first_paid_at) AS quarter,
count(*) AS new_customers
FROM customers
WHERE first_paid_at IS NOT NULL
GROUP BY 1
)
SELECT
s.quarter,
s.total_spend,
c.new_customers,
round(s.total_spend / NULLIF(c.new_customers, 0), 2) AS blended_cac
FROM quarterly_spend s
JOIN quarterly_new_customers c USING (quarter)
ORDER BY 1 DESC;
-- Separate CAC by channel (if UTM tracking is available)
SELECT
attribution_channel,
count(*) AS customers,
sum(first_month_acv) AS total_acv,
round(sum(acquisition_cost) / NULLIF(count(*), 0), 2) AS channel_cac
FROM customer_attribution
WHERE first_paid_at >= now() - interval '12 months'
GROUP BY 1
ORDER BY channel_cac;
CAC Benchmarks by Segment
| Segment | Average CAC | Range |
|---|---|---|
| SMB (self-serve) | $100โ$500 | $50โ$2,000 |
| Mid-market | $3,000โ$10,000 | $1,000โ$25,000 |
| Enterprise | $20,000โ$80,000 | $10,000โ$200,000+ |
๐ก The Difference Between a SaaS Demo and a SaaS Business
Anyone can build a demo. We build SaaS products that handle real load, real users, and real payments โ with architecture that does not need to be rewritten at 1,000 users.
- Multi-tenant PostgreSQL with row-level security
- Stripe subscriptions, usage billing, annual plans
- SOC2-ready infrastructure from day one
- We own zero equity โ you own everything
LTV and CAC:LTV Ratio
LTV (Customer Lifetime Value) = ARPU / Gross Churn Rate
-- LTV calculation by customer segment
WITH segment_metrics AS (
SELECT
CASE
WHEN mrr_amount >= 1000 THEN 'enterprise'
WHEN mrr_amount >= 200 THEN 'mid_market'
ELSE 'smb'
END AS segment,
count(*) AS customers,
avg(mrr_amount) AS avg_mrr,
-- Gross logo churn rate (monthly)
count(*) FILTER (WHERE cancelled_at >= now() - interval '30 days') /
NULLIF(count(*), 0)::float AS monthly_logo_churn
FROM subscriptions
WHERE started_at <= now() - interval '1 month'
GROUP BY 1
)
SELECT
segment,
customers,
round(avg_mrr, 2) AS avg_mrr,
round(monthly_logo_churn * 100, 2) AS monthly_churn_pct,
-- LTV = ARPU / monthly churn rate ร gross margin (assume 75%)
round(avg_mrr * 0.75 / NULLIF(monthly_logo_churn, 0), 0) AS ltv_usd,
-- CAC:LTV (needs CAC from other source)
NULL AS cac_to_ltv_ratio -- Fill in from CAC table
FROM segment_metrics;
CAC:LTV Targets
| Ratio | Interpretation |
|---|---|
| <1:1 | Losing money on every customer โ unsustainable |
| 1:1 โ 3:1 | Marginal; need to either cut CAC or grow LTV |
| 3:1 | Healthy minimum for VC-backed SaaS |
| 5:1 โ 8:1 | Excellent; may be underinvesting in growth |
| >10:1 | Great product economics; aggressive growth makes sense |
Rule of 40
Rule of 40 = ARR Growth Rate (%) + EBITDA Margin (%)
- Score โฅ 40 = healthy for VC/growth stage
- Score โฅ 60 = excellent; "Rule of 60" for elite SaaS
- Score <40 for multiple quarters = requires attention
# Calculate Rule of 40
def rule_of_40(
current_arr: float,
prior_year_arr: float,
ebitda: float,
revenue: float,
) -> float:
arr_growth_pct = (current_arr - prior_year_arr) / prior_year_arr * 100
ebitda_margin_pct = ebitda / revenue * 100
return arr_growth_pct + ebitda_margin_pct
# Examples:
# High-growth startup: 150% growth + (-80%) margin = 70 โ
# Profitable slow-growth: 20% growth + 25% margin = 45 โ
# Struggling: 15% growth + (-30%) margin = -15 โ
Rule of 40 Benchmarks (Public SaaS, 2026)
| Company Stage | Median Rule of 40 | Top Quartile |
|---|---|---|
| $1Mโ$10M ARR | 20โ40 | >60 |
| $10Mโ$50M ARR | 30โ50 | >70 |
| $50Mโ$200M ARR | 35โ55 | >75 |
| $200M+ ARR | 40โ60 | >80 |
Churn Rate Calculations
-- Monthly gross logo churn rate
SELECT
date_trunc('month', cancelled_at) AS month,
count(*) AS churned_customers,
-- Denominator: customers active at start of month
(SELECT count(*)
FROM subscriptions s2
WHERE s2.status = 'active'
AND s2.started_at < date_trunc('month', s.cancelled_at)
AND (s2.cancelled_at IS NULL OR s2.cancelled_at >= date_trunc('month', s.cancelled_at))
) AS starting_customers,
round(
count(*)::numeric /
NULLIF((SELECT count(*)
FROM subscriptions s2
WHERE s2.started_at < date_trunc('month', s.cancelled_at)
AND (s2.cancelled_at IS NULL OR s2.cancelled_at >= date_trunc('month', s.cancelled_at))
), 0) * 100, 2
) AS logo_churn_rate_pct
FROM subscriptions s
WHERE cancelled_at >= now() - interval '12 months'
GROUP BY 1
ORDER BY 1;
Churn Rate Benchmarks
| Segment | Monthly Churn | Annual Churn | Notes |
|---|---|---|---|
| SMB self-serve | 3โ7% | 36โ84% | High; offset by high-volume acquisition |
| Mid-market | 1โ2.5% | 12โ30% | Important to reduce via CS |
| Enterprise | 0.25โ1% | 3โ12% | Long contracts help; hard to recover from |
| Best-in-class (any) | <0.5% | <6% | NPS promoters, strong CS |
CAC Payback Period
How many months to recoup the cost of acquiring a customer:
CAC Payback = CAC / (ARPU ร Gross Margin)
| Stage | Acceptable Payback | Good | Best-in-Class |
|---|---|---|---|
| Self-serve | <12 months | <6 months | <3 months |
| Mid-market | <18 months | <12 months | <9 months |
| Enterprise | <24 months | <18 months | <12 months |
Metrics Dashboard Implementation
// src/analytics/saas-metrics.ts
export async function getSaaSMetrics(asOfDate: Date): Promise<SaaSMetrics> {
const [mrr, nrr, mrrMovement, churnRate] = await Promise.all([
db.query<{ mrr: number; arr: number; customer_count: number }>(MRR_QUERY, [asOfDate]),
db.query<{ nrr_pct: number }>(NRR_QUERY),
db.query<MRRMovement[]>(MRR_MOVEMENT_QUERY),
db.query<{ logo_churn_rate_pct: number }>(CHURN_RATE_QUERY),
]);
const mrrRow = mrr.rows[0];
const nrrRow = nrr.rows[0];
return {
mrr: mrrRow.mrr,
arr: mrrRow.arr,
activeCustomers: mrrRow.customer_count,
nrr: nrrRow.nrr_pct,
monthlyChurnRate: churnRate.rows[0]?.logo_churn_rate_pct ?? 0,
mrrMovement: mrrMovement.rows,
computedAt: new Date(),
};
}
Working With Viprasol
We build SaaS metrics infrastructure for growth-stage companies โ from clean data pipelines through investor-ready dashboards and automated reporting.
What we deliver:
- MRR/ARR tracking with proper event sourcing (new, expansion, contraction, churn)
- NRR calculation with cohort analysis
- CAC and LTV attribution by channel and segment
- Rule of 40 and unit economics dashboard
- Automated weekly metrics email to founders and investors
โ Discuss your metrics infrastructure โ AI and analytics services
About the Author
Viprasol Tech Team
Custom Software Development Specialists
The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.
Building a SaaS Product?
We've helped launch 50+ SaaS platforms. Let's build yours โ fast.
Free consultation โข No commitment โข Response within 24 hours
Add AI automation to your SaaS product?
Viprasol builds custom AI agent crews that plug into any SaaS workflow โ automating repetitive tasks, qualifying leads, and responding across every channel your customers use.