The LTV:CAC ratio compares the lifetime value generated by a cohort of customers to the cost of acquiring those customers, enabling companies to judge the efficiency and scalability of their go-to-market strategy.
LTV:CAC is one of the most quoted SaaS metrics—but too often it’s calculated in an ad-hoc Google Sheet rather than in a production-grade data model. In this article you’ll learn how to architect the data, write the SQL, and expose the ratio in any modern BI tool or SQL editor.
We’ll cover data requirements, cohorting logic, SQL examples, visualization tips, and common pitfalls, with special notes on how developer-focused editors like Galaxy streamline the workflow.
Customer Lifetime Value (LTV) is the net revenue a customer is expected to generate over their entire relationship with your business. Customer Acquisition Cost (CAC) is the total expense required to acquire that customer. The LTV:CAC ratio divides the two:
LTV:CAC = Lifetime Value per Customer ÷ Acquisition Cost per Customer
A ratio > 1.0 means you earn more than you spend; SaaS benchmarks typically target 3:1 for healthy growth.
Ideally a table at the transaction level (e.g., invoices, Stripe charges) with:
customer_id
invoice_date
amount
(net of refunds)Marketing platform exports or finance ledger entries with:
campaign_id
, source
, or channel
spend_date
spend_amount
Contains attributes needed for drill-downs and connects acquisition to revenue through fields such as first_touch_campaign_id
, signup_date
, and plan_tier
.
Cohorting by signup_month
is common:
WITH customer_cohorts AS (
SELECT
customer_id,
DATE_TRUNC('month', signup_date) AS cohort_month
FROM dim_customers
)
, revenue_per_customer AS (
SELECT
c.customer_id,
SUM(r.amount) AS lifetime_revenue
FROM customer_cohorts c
JOIN fact_revenue r USING (customer_id)
GROUP BY 1
)
Single-touch attribution shown for clarity; adapt for multi-touch if needed.
, cac_per_customer AS (
SELECT
d.customer_id,
COALESCE(SUM(s.spend_amount),0) AS cac
FROM dim_customers d
LEFT JOIN fact_spend s
ON s.campaign_id = d.first_touch_campaign_id
GROUP BY 1
)
SELECT
DATE_TRUNC('month', d.signup_date) AS cohort_month,
AVG(r.lifetime_revenue) AS avg_ltv,
AVG(c.cac) AS avg_cac,
CASE
WHEN AVG(c.cac) = 0 THEN NULL
ELSE AVG(r.lifetime_revenue) / AVG(c.cac)
END AS ltv_cac_ratio
FROM dim_customers d
JOIN revenue_per_customer r USING (customer_id)
JOIN cac_per_customer c USING (customer_id)
GROUP BY 1
ORDER BY 1;
If you’re building these queries in Galaxy’s desktop SQL editor:
:cohort_window
variables so analysts can explore payback periods interactively.avg_ltv
and avg_cac
to keep your data catalog in sync.first_touch_campaign_id
is mutable, you’ll see historical restatements. Snapshot or slowly-changing dimension those keys.The snippet below creates an explorable view that your BI tool—or Galaxy’s preview chart—can point to directly.
CREATE OR REPLACE VIEW analytics.v_ltv_cac_monthly AS
WITH customer_cohorts AS (
SELECT customer_id,
DATE_TRUNC('month', signup_date) AS cohort_month
FROM dim_customers
),
revenue_per_customer AS (
SELECT c.customer_id,
SUM(r.amount) AS lifetime_revenue
FROM customer_cohorts c
JOIN fact_revenue r USING (customer_id)
GROUP BY 1
),
cac_per_customer AS (
SELECT d.customer_id,
COALESCE(SUM(s.spend_amount),0) AS cac
FROM dim_customers d
LEFT JOIN fact_spend s
ON s.campaign_id = d.first_touch_campaign_id
GROUP BY 1
)
SELECT cohort_month,
AVG(lifetime_revenue) AS avg_ltv,
AVG(cac) AS avg_cac,
CASE WHEN AVG(cac)=0 THEN NULL ELSE AVG(lifetime_revenue)/AVG(cac) END AS ltv_cac_ratio
FROM customer_cohorts cc
JOIN revenue_per_customer rpc USING (customer_id)
JOIN cac_per_customer cpc USING (customer_id)
GROUP BY cohort_month
ORDER BY cohort_month;
Once this view is materialized, simply add it as a dataset in Looker, Tableau, Metabase—or query it live in Galaxy.
High-growth companies often set thresholds: if the ratio dips below 2.5 for > 7 days, notify Finance. Many BI platforms let you schedule alerts, or you can create a dbt test that fails CI when the metric degrades.
LTV:CAC is a core efficiency metric: it reveals whether your company creates more long-term value than it spends on customer acquisition. By embedding the ratio in your BI layer—rather than spreadsheets—you gain real-time insight, can segment by channel or cohort, and foster cross-team alignment on growth decisions. Solid data modeling also makes the metric auditable for investors and reduces errors as your data volume scales.
Most teams recalculate daily using incremental ELT and materialize a view. If your spend or revenue sources update intraday, consider hourly refreshes.
Keep the zero value but handle division by zero carefully (e.g., return NULL). Many analysts also segment organic separately to avoid skewing paid ratios.
Galaxy’s SQL editor lets you version and share the ratio query in a Collection. Its AI copilot suggests optimizations—like converting correlated subqueries into CTEs—making the calculation faster and cheaper.
No. Hardware businesses may need higher ratios, while high-retention SaaS can justify 2:1 during hyper-growth. Context and gross margin matter.