Cohort analysis
The retention triangle every PM asks for — assign users to a signup cohort, measure their activity month by month, and pivot it into the analyst flagship.
What you'll learn
- Assigning each user a cohort (their signup month)
- Computing per-cohort activity in each later month
- Normalising counts into retention percentages
- Pivoting the long form into the wide 'triangle'
Before you start
Every PM asks for it eventually: “How sticky are our users? What’s month-1 retention by signup month?” The answer is a cohort retention table — a triangle where each row is a cohort (everyone who started in the same month), each column is a month-since-signup, and each cell is the share of that cohort still active then.
It is the analyst’s flagship deliverable, and it is entirely SQL once you break it into four named steps: assign each user a cohort, flag their active months, join activity against tenure, and pivot into the wide shape. CTEs are made for this — one per step.
The build
Cohort and activity month come from truncating dates to the month (SQLite’s strftime('%Y-%m', …)). Tenure is the gap between them, and retention is active users over cohort size:
WITH cohorts AS (
SELECT id AS user_id, strftime('%Y-%m', signup_date) AS cohort_month
FROM users
),
sizes AS (
SELECT cohort_month, COUNT(*) AS cohort_size FROM cohorts GROUP BY cohort_month
),
activity AS (
SELECT DISTINCT user_id, strftime('%Y-%m', order_date) AS active_month
FROM orders
),
retention AS (
SELECT c.cohort_month,
CAST((julianday(a.active_month || '-01') - julianday(c.cohort_month || '-01')) / 30 AS INT) AS m,
COUNT(DISTINCT c.user_id) AS active_users
FROM cohorts c
JOIN activity a ON a.user_id = c.user_id
GROUP BY c.cohort_month, m
)
SELECT r.cohort_month, s.cohort_size,
ROUND(100.0 * MAX(CASE WHEN m = 0 THEN active_users END) / s.cohort_size, 1) AS m0,
ROUND(100.0 * MAX(CASE WHEN m = 1 THEN active_users END) / s.cohort_size, 1) AS m1
FROM retention r
JOIN sizes s ON s.cohort_month = r.cohort_month
GROUP BY r.cohort_month, s.cohort_size
ORDER BY r.cohort_month;
The one new idiom is MAX(CASE WHEN m = N THEN active_users END) — conditional aggregation, which pulls each tenure month into its own column (SQLite has no PIVOT). On a tiny dataset — a 3-user January cohort and a 4-user February cohort — it produces the triangle:
Two things make this a real artifact rather than a pile of counts. Dividing by cohort_size turns raw active-user counts into percentages, which is the only way to compare cohorts of different sizes — 50 actives means nothing until you know the cohort was 100 or 10,000. And the triangle shape is not a bug: a cohort that signed up last month simply cannot have a month-1 number yet, so the bottom-right is empty.
Practice
Quick check
Practice this in an interview
All questionsA retention drop investigation requires distinguishing between an acquisition-mix shift (newer cohorts are lower quality) and a genuine product regression (existing cohorts are performing worse). The two look identical in aggregate retention but have completely different fixes. Cohort analysis — plotting the D30 survival curve for each weekly acquisition cohort — is the first move.
Engagement is multi-dimensional: breadth (how many users engage), depth (how much they do per session), and frequency (how often they return). A robust engagement framework stacks these three layers into a metric hierarchy and links them to retention curves, because engagement that does not predict long-term retention is usually noise.
Lagging indicators (revenue, annual retention, NPS) measure outcomes after they have occurred — they are accurate but slow. Leading indicators (D1 retention, feature adoption rate, time-to-value) correlate with future outcomes and are available faster, making them suitable for early experiment decisions. A robust metrics system pairs both, with the leading metric as the experiment signal and the lagging metric as the validation gate.
The ML lifecycle spans eight phases: problem framing, data collection and validation, feature engineering, training and experimentation, offline evaluation, deployment, production monitoring, and retirement or retraining. Each phase has distinct owners, artefacts, and failure modes that an MLOps practice must systematise.