SAAS

Monthly Recurring Revenue (MRR)

Snapshot monthly subscription income — SQL to split new, expansion and churn MRR.

In the dynamic world of SaaS, data is your roadmap to clarity and confidence.

This playbook equips you with ready-to-use SQL queries for the metrics that drive growth, retention, and profitability.

No need for advanced technical skills—just adapt the table and column names to your database, and let the insights unfold.

How to Use This Playbook

  1. Choose your metric.
    Find the metric that answers your most pressing questions.
  2. Copy the SQL.
    Swap in your own table and column names.
  3. Run it in your database tool.
    Watch as the numbers reveal your business’s story.

Industry Benchmarks & Standards

Metric Industry Benchmark (2025) What It Means
Net Revenue Retention (NRR) 101% (B2B SaaS median) Above 100% means your customers are growing their investment.
Customer Churn Rate 5% - 10% (varies by segment) Lower is better; aim for <5% in high-growth SaaS.
Annual Recurring Revenue (ARR) Growth Rate 17% - 26% (median, varies by size) Top performers can exceed 50%.
DAU/MAU Ratio 20% - 50% (varies by product) Higher means your users are truly engaged.
LTV/CAC Ratio 3:1 or higher Ensures your business model is robust and sustainable.
Contribution Margin 70% - 85% (healthy SaaS) Direct costs should be a small slice of your revenue pie.
Average Revenue Per User (ARPU) Varies by segment Higher ARPU means your customers find more value in your product.

Your Data Foundation

These tables are the pillars of your SaaS analytics:

  • main.saas_data_clients: The foundation of every client relationship.
    • client_id, client_name, created_at
  • main.saas_data_customers: Every user’s journey, captured in detail.
    • customer_id, client_id, customer_name, signup_date, is_active
  • main.saas_data_plans: Your product’s menu of options.
    • plan_id, client_id, plan_name, monthly_price, annual_price, is_active
  • main.saas_data_subscriptions: Captures the full lifecycle: sign-ups, renewals, and cancellations.
    • subscription_id, client_id, customer_id, plan_id, start_date, end_date, status
  • main.saas_data_payments: The flow of revenue through your business.
    • payment_id, client_id, customer_id, subscription_id, amount, payment_date, is_refund
  • main.saas_data_events: The story of every login, upgrade, and farewell.
    • event_id, client_id, customer_id, event_type, event_date, is_churn
  • main.saas_data_costs: The price of delivering value to your customers.
    • cost_id, client_id, customer_id, cost_type, cost_amount, cost_date

1. Monthly Recurring Revenue (MRR) –

All ComponentsMRR is your business’s financial pulse—predictable, measurable, and essential. Tracking its components (new, expansion, contraction, churn, reactivation, net new, committed) reveals the engines of growth and the risks to watch.

Source Table Columns used
main.saas_data_subscriptions start_date, end_date, status, plan_id, customer_id
main.saas_data_payments payment_date
main.saas_data_events event_date, event_type, customer_id, is_churn
main.saas_data_plans plan_id, monthly_price
WITH
-- All months with any MRR activity
"all_months" AS (
  SELECT DISTINCT
    DATE_TRUNC('month', "month_data"."month") AS "month"
  FROM (
    SELECT "start_date" AS "month" FROM "main"."saas_data_subscriptions"
    UNION ALL SELECT "payment_date" FROM "main"."saas_data_payments"
    UNION ALL SELECT "event_date" FROM "main"."saas_data_events"
  ) AS "month_data"
),

-- New MRR: First subscription for a customer
"new_mrr" AS (
  SELECT
    DATE_TRUNC('month', "subscriptions"."start_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "new_mrr"
  FROM "main"."saas_data_subscriptions" AS "subscriptions"
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE NOT EXISTS (
    SELECT 1
    FROM "main"."saas_data_subscriptions" AS "previous_subscriptions"
    WHERE "previous_subscriptions"."customer_id" = "subscriptions"."customer_id"
      AND "previous_subscriptions"."start_date" < "subscriptions"."start_date"
  )
  GROUP BY 1
),

-- Expansion MRR
"expansion_mrr" AS (
  SELECT
    DATE_TRUNC('month', "events"."event_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "expansion_mrr"
  FROM "main"."saas_data_events" AS "events"
  JOIN "main"."saas_data_subscriptions" AS "subscriptions"
    ON "events"."customer_id" = "subscriptions"."customer_id"
    AND "events"."event_date" BETWEEN "subscriptions"."start_date" AND COALESCE("subscriptions"."end_date", CURRENT_DATE)
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "events"."event_type" = 'upgrade'
  GROUP BY 1
),

-- Contraction MRR
"contraction_mrr" AS (
  SELECT
    DATE_TRUNC('month', "events"."event_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "contraction_mrr"
  FROM "main"."saas_data_events" AS "events"
  JOIN "main"."saas_data_subscriptions" AS "subscriptions"
    ON "events"."customer_id" = "subscriptions"."customer_id"
    AND "events"."event_date" BETWEEN "subscriptions"."start_date" AND COALESCE("subscriptions"."end_date", CURRENT_DATE)
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "events"."event_type" = 'downgrade'
  GROUP BY 1
),

-- Churn MRR
"churn_mrr" AS (
  SELECT
    DATE_TRUNC('month', "events"."event_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "churn_mrr"
  FROM "main"."saas_data_events" AS "events"
  JOIN "main"."saas_data_subscriptions" AS "subscriptions"
    ON "events"."customer_id" = "subscriptions"."customer_id"
    AND "events"."event_date" BETWEEN "subscriptions"."start_date" AND COALESCE("subscriptions"."end_date", CURRENT_DATE)
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "events"."is_churn" = TRUE
  GROUP BY 1
),

-- Reactivation MRR
"reactivation_mrr" AS (
  SELECT
    DATE_TRUNC('month', "subscriptions"."start_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "reactivation_mrr"
  FROM "main"."saas_data_subscriptions" AS "subscriptions"
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE EXISTS (
    SELECT 1
    FROM "main"."saas_data_events" AS "events"
    WHERE "events"."customer_id" = "subscriptions"."customer_id"
      AND "events"."is_churn" = TRUE
      AND "events"."event_date" < "subscriptions"."start_date"
  )
  GROUP BY 1
),

-- Committed MRR
"committed_mrr" AS (
  SELECT
    DATE_TRUNC('month', "subscriptions"."start_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "committed_mrr"
  FROM "main"."saas_data_subscriptions" AS "subscriptions"
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "subscriptions"."status" = 'active'
  GROUP BY 1
)

SELECT
  "all_months"."month" AS "date",
  ROUND(COALESCE("new_mrr"."new_mrr", 0), 2) AS "new_mrr",
  ROUND(COALESCE("expansion_mrr"."expansion_mrr", 0), 2) AS "expansion_mrr",
  ROUND(COALESCE("contraction_mrr"."contraction_mrr", 0), 2) AS "contraction_mrr",
  ROUND(COALESCE("churn_mrr"."churn_mrr", 0), 2) AS "churn_mrr",
  ROUND(COALESCE("reactivation_mrr"."reactivation_mrr", 0), 2) AS "reactivation_mrr",
  ROUND(
    COALESCE("new_mrr"."new_mrr", 0) +
    COALESCE("expansion_mrr"."expansion_mrr", 0) -
    COALESCE("contraction_mrr"."contraction_mrr", 0) -
    COALESCE("churn_mrr"."churn_mrr", 0) +
    COALESCE("reactivation_mrr"."reactivation_mrr", 0),
    2
  ) AS "net_new_mrr",
  ROUND(COALESCE("committed_mrr"."committed_mrr", 0), 2) AS "committed_mrr"
FROM "all_months"
LEFT JOIN "new_mrr" ON "all_months"."month" = "new_mrr"."month"
LEFT JOIN "expansion_mrr" ON "all_months"."month" = "expansion_mrr"."month"
LEFT JOIN "contraction_mrr" ON "all_months"."month" = "contraction_mrr"."month"
LEFT JOIN "churn_mrr" ON "all_months"."month" = "churn_mrr"."month"
LEFT JOIN "reactivation_mrr" ON "all_months"."month" = "reactivation_mrr"."month"
LEFT JOIN "committed_mrr" ON "all_months"."month" = "committed_mrr"."month"
ORDER BY "all_months"."month"

Visualization Ideas:

  • Line Chart: Watch each MRR component move through time.
  • Stacked Bar Chart: View the full story of growth and loss, color by color.
  • Scorecard: Make net new MRR or committed MRR your headline.

Implementation Checklist

  1. Define your metrics and add them to a data dictionary.
  2. Ensure your database schema supports the required calculations.
  3. Write and test SQL queries for each metric.
  4. Import results into your BI tool. Get started with DataBrain today!
  5. Build and share dashboards with stakeholders.
  6. Schedule regular reviews and updates.

Unlock the power of your data.
Start using this SQL Playbook today!

“In the world of SaaS, data is everyone’s responsibility. With this playbook, anyone can own their metrics and drive better outcomes.”

Now, simply run the SQL queries on your data and unlock the power of your SaaS analytics!

In the dynamic world of SaaS, data is your roadmap to clarity and confidence.

This playbook equips you with ready-to-use SQL queries for the metrics that drive growth, retention, and profitability.

No need for advanced technical skills—just adapt the table and column names to your database, and let the insights unfold.

How to Use This Playbook

  1. Choose your metric.
    Find the metric that answers your most pressing questions.
  2. Copy the SQL.
    Swap in your own table and column names.
  3. Run it in your database tool.
    Watch as the numbers reveal your business’s story.

Industry Benchmarks & Standards

Metric Industry Benchmark (2025) What It Means
Net Revenue Retention (NRR) 101% (B2B SaaS median) Above 100% means your customers are growing their investment.
Customer Churn Rate 5% - 10% (varies by segment) Lower is better; aim for <5% in high-growth SaaS.
Annual Recurring Revenue (ARR) Growth Rate 17% - 26% (median, varies by size) Top performers can exceed 50%.
DAU/MAU Ratio 20% - 50% (varies by product) Higher means your users are truly engaged.
LTV/CAC Ratio 3:1 or higher Ensures your business model is robust and sustainable.
Contribution Margin 70% - 85% (healthy SaaS) Direct costs should be a small slice of your revenue pie.
Average Revenue Per User (ARPU) Varies by segment Higher ARPU means your customers find more value in your product.

Your Data Foundation

These tables are the pillars of your SaaS analytics:

  • main.saas_data_clients: The foundation of every client relationship.
    • client_id, client_name, created_at
  • main.saas_data_customers: Every user’s journey, captured in detail.
    • customer_id, client_id, customer_name, signup_date, is_active
  • main.saas_data_plans: Your product’s menu of options.
    • plan_id, client_id, plan_name, monthly_price, annual_price, is_active
  • main.saas_data_subscriptions: Captures the full lifecycle: sign-ups, renewals, and cancellations.
    • subscription_id, client_id, customer_id, plan_id, start_date, end_date, status
  • main.saas_data_payments: The flow of revenue through your business.
    • payment_id, client_id, customer_id, subscription_id, amount, payment_date, is_refund
  • main.saas_data_events: The story of every login, upgrade, and farewell.
    • event_id, client_id, customer_id, event_type, event_date, is_churn
  • main.saas_data_costs: The price of delivering value to your customers.
    • cost_id, client_id, customer_id, cost_type, cost_amount, cost_date

1. Monthly Recurring Revenue (MRR) –

All ComponentsMRR is your business’s financial pulse—predictable, measurable, and essential. Tracking its components (new, expansion, contraction, churn, reactivation, net new, committed) reveals the engines of growth and the risks to watch.

Source Table Columns used
main.saas_data_subscriptions start_date, end_date, status, plan_id, customer_id
main.saas_data_payments payment_date
main.saas_data_events event_date, event_type, customer_id, is_churn
main.saas_data_plans plan_id, monthly_price
WITH
-- All months with any MRR activity
"all_months" AS (
  SELECT DISTINCT
    DATE_TRUNC('month', "month_data"."month") AS "month"
  FROM (
    SELECT "start_date" AS "month" FROM "main"."saas_data_subscriptions"
    UNION ALL SELECT "payment_date" FROM "main"."saas_data_payments"
    UNION ALL SELECT "event_date" FROM "main"."saas_data_events"
  ) AS "month_data"
),

-- New MRR: First subscription for a customer
"new_mrr" AS (
  SELECT
    DATE_TRUNC('month', "subscriptions"."start_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "new_mrr"
  FROM "main"."saas_data_subscriptions" AS "subscriptions"
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE NOT EXISTS (
    SELECT 1
    FROM "main"."saas_data_subscriptions" AS "previous_subscriptions"
    WHERE "previous_subscriptions"."customer_id" = "subscriptions"."customer_id"
      AND "previous_subscriptions"."start_date" < "subscriptions"."start_date"
  )
  GROUP BY 1
),

-- Expansion MRR
"expansion_mrr" AS (
  SELECT
    DATE_TRUNC('month', "events"."event_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "expansion_mrr"
  FROM "main"."saas_data_events" AS "events"
  JOIN "main"."saas_data_subscriptions" AS "subscriptions"
    ON "events"."customer_id" = "subscriptions"."customer_id"
    AND "events"."event_date" BETWEEN "subscriptions"."start_date" AND COALESCE("subscriptions"."end_date", CURRENT_DATE)
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "events"."event_type" = 'upgrade'
  GROUP BY 1
),

-- Contraction MRR
"contraction_mrr" AS (
  SELECT
    DATE_TRUNC('month', "events"."event_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "contraction_mrr"
  FROM "main"."saas_data_events" AS "events"
  JOIN "main"."saas_data_subscriptions" AS "subscriptions"
    ON "events"."customer_id" = "subscriptions"."customer_id"
    AND "events"."event_date" BETWEEN "subscriptions"."start_date" AND COALESCE("subscriptions"."end_date", CURRENT_DATE)
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "events"."event_type" = 'downgrade'
  GROUP BY 1
),

-- Churn MRR
"churn_mrr" AS (
  SELECT
    DATE_TRUNC('month', "events"."event_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "churn_mrr"
  FROM "main"."saas_data_events" AS "events"
  JOIN "main"."saas_data_subscriptions" AS "subscriptions"
    ON "events"."customer_id" = "subscriptions"."customer_id"
    AND "events"."event_date" BETWEEN "subscriptions"."start_date" AND COALESCE("subscriptions"."end_date", CURRENT_DATE)
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "events"."is_churn" = TRUE
  GROUP BY 1
),

-- Reactivation MRR
"reactivation_mrr" AS (
  SELECT
    DATE_TRUNC('month', "subscriptions"."start_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "reactivation_mrr"
  FROM "main"."saas_data_subscriptions" AS "subscriptions"
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE EXISTS (
    SELECT 1
    FROM "main"."saas_data_events" AS "events"
    WHERE "events"."customer_id" = "subscriptions"."customer_id"
      AND "events"."is_churn" = TRUE
      AND "events"."event_date" < "subscriptions"."start_date"
  )
  GROUP BY 1
),

-- Committed MRR
"committed_mrr" AS (
  SELECT
    DATE_TRUNC('month', "subscriptions"."start_date") AS "month",
    ROUND(SUM("plans"."monthly_price")::DOUBLE, 2) AS "committed_mrr"
  FROM "main"."saas_data_subscriptions" AS "subscriptions"
  JOIN "main"."saas_data_plans" AS "plans" ON "subscriptions"."plan_id" = "plans"."plan_id"
  WHERE "subscriptions"."status" = 'active'
  GROUP BY 1
)

SELECT
  "all_months"."month" AS "date",
  ROUND(COALESCE("new_mrr"."new_mrr", 0), 2) AS "new_mrr",
  ROUND(COALESCE("expansion_mrr"."expansion_mrr", 0), 2) AS "expansion_mrr",
  ROUND(COALESCE("contraction_mrr"."contraction_mrr", 0), 2) AS "contraction_mrr",
  ROUND(COALESCE("churn_mrr"."churn_mrr", 0), 2) AS "churn_mrr",
  ROUND(COALESCE("reactivation_mrr"."reactivation_mrr", 0), 2) AS "reactivation_mrr",
  ROUND(
    COALESCE("new_mrr"."new_mrr", 0) +
    COALESCE("expansion_mrr"."expansion_mrr", 0) -
    COALESCE("contraction_mrr"."contraction_mrr", 0) -
    COALESCE("churn_mrr"."churn_mrr", 0) +
    COALESCE("reactivation_mrr"."reactivation_mrr", 0),
    2
  ) AS "net_new_mrr",
  ROUND(COALESCE("committed_mrr"."committed_mrr", 0), 2) AS "committed_mrr"
FROM "all_months"
LEFT JOIN "new_mrr" ON "all_months"."month" = "new_mrr"."month"
LEFT JOIN "expansion_mrr" ON "all_months"."month" = "expansion_mrr"."month"
LEFT JOIN "contraction_mrr" ON "all_months"."month" = "contraction_mrr"."month"
LEFT JOIN "churn_mrr" ON "all_months"."month" = "churn_mrr"."month"
LEFT JOIN "reactivation_mrr" ON "all_months"."month" = "reactivation_mrr"."month"
LEFT JOIN "committed_mrr" ON "all_months"."month" = "committed_mrr"."month"
ORDER BY "all_months"."month"

Visualization Ideas:

  • Line Chart: Watch each MRR component move through time.
  • Stacked Bar Chart: View the full story of growth and loss, color by color.
  • Scorecard: Make net new MRR or committed MRR your headline.

Implementation Checklist

  1. Define your metrics and add them to a data dictionary.
  2. Ensure your database schema supports the required calculations.
  3. Write and test SQL queries for each metric.
  4. Import results into your BI tool. Get started with DataBrain today!
  5. Build and share dashboards with stakeholders.
  6. Schedule regular reviews and updates.

Unlock the power of your data.
Start using this SQL Playbook today!

“In the world of SaaS, data is everyone’s responsibility. With this playbook, anyone can own their metrics and drive better outcomes.”

Now, simply run the SQL queries on your data and unlock the power of your SaaS analytics!

Make analytics your competitive advantage

Get it touch with us and see how Databrain can take your customer-facing analytics to the next level.

Interactive analytics dashboard with revenue insights, sales stats, and active deals powered by Databrain