How to Plot a Retention Curve (and Not Fool Yourself)
A retention curve is one line, but four decisions sit underneath it: what counts as retained, which rhythm you measure on, how you average your cohorts, and what you plot on top. Get the averaging wrong and a product that keeps 38% of its users forever looks like it keeps 5%. Here's the method, with a plotter you can paste your own numbers into.
TLDR: A retention curve is one line, but four decisions sit underneath it, and getting any one of them wrong changes the line before anybody has looked at the shape.
Decide what "retained" means first. One core action that shows value, measured on your product's natural rhythm, for a named group of users. Not logins.
Build cohorts by signup period and count, for each one, how many did the core action in each period after signup.
Average each period only over cohorts that have reached it, weighted by cohort size. Counting young cohorts as zero turns a 38% plateau into a slide to 5%.
Plot time since signup on the x-axis and 0 to 100% on the y-axis, and stop the line where the data gets thin.
Then overlay individual cohorts and segments, because the average hides most of what you need to know.
The method is the one Reforge teaches in its retention material. Brian Balfour and Casey Winters wrote the short version in Why Retention Is the Silent Killer. What follows is that method step by step, with the mistakes that do the most damage, and a plotter near the end where you can paste your own numbers.
What is a retention curve, and why plot it at all?
A retention curve shows the share of a group of users still doing your core action N days, weeks or months after they started. Time since signup goes along the bottom. Percentage still active goes up the side. It starts at 100% and drops.
The reason to plot it instead of quoting a churn rate is that two products with the same churn number can be in completely different situations. One loses a big chunk of new users early and then keeps everybody else for years. The other loses a steady slice every month until there's nothing left. A single number averages those two stories into one. The curve shows which one you're in. I made that argument at length in your churn rate is lying to you, so here I'm going to stay on the practical side: how to draw the thing so it's telling you the truth.
The question a retention curve answers is "does it flatten, and at what level?" Everything in this post is about making sure the answer you see is the real one.
Step 1: What should count as "retained"?
This is the decision that changes your curve the most, and it's the one most teams skip because their analytics tool defaults to "any event". Reforge breaks a retention metric into three parts: frequency, core behaviour and who.
Frequency: which rhythm do you measure on?
Your product has a natural rhythm, the gap between sessions when nothing is nudging people back. Measure retention on that rhythm. If you don't, the curve lies in a predictable direction: a weekly product measured daily looks like it's haemorrhaging users, and a daily product measured monthly hides a problem for weeks.
The quickest way to find the rhythm is a histogram. Take your paying customers, count how many of the last 28 days each one did the core action, and chart how many customers landed on each count.
If most customers cluster at 20 or more days, you're daily. Around 3 to 7, weekly. One or two, monthly. If you see two clusters, you probably have two kinds of customer using the product for two different jobs, and they deserve two separate curves. I went further into natural frequency, including how to strip out sessions your emails caused, in trial length should match your usage frequency.
Core behaviour: which action means they got value?
Pick the simplest action that shows the customer actually got something out of you. Not a login. For an invoicing tool it's an invoice sent. For a reporting tool it might be a report shared. If you can't name it in one sentence, finding your aha moment is the job to do first.
The good news is you don't have to guess. Plot the curve for two or three candidate actions on the same customers and compare the tails.
Logins nearly always win in month one and lose by month six, because people check in without getting anything done. Pick the action with the flattest, highest tail, even if its first-month number looks worse. And don't combine actions into one metric ("logged in OR created a report OR invited someone"). Teams then push whichever one is easiest to move, and the curve goes up while nothing real improves.
Who: which users are in the curve?
Be explicit about who's in the denominator. Paying accounts, or every signup including free users? Individual users, or whole accounts? For B2B the account usually matters more, because one churned account of 40 seats is a bigger deal than 40 unrelated users going quiet. Write the definition down where the chart lives. Pinterest's version, quoted in the Reforge material, was "weekly active repinners", which tells you the rhythm, the action and the user in three words.
Step 2: How do you get the raw data?
You need two things per user: when they started (which cohort they're in) and each period in which they did the core action. That's it. Revenue, plan and channel are useful later for segmenting, but the curve itself only needs those two.
If your events live in a database, this Postgres query gets you monthly cohorts. Swap the event name for your own core action:
with cohorts as (
select id as user_id,
date_trunc('month', created_at) as cohort_month
from users
where created_at >= '2026-01-01'
),
activity as (
select distinct user_id,
date_trunc('month', occurred_at) as active_month
from events
where name = 'report_shared' -- your core action, not a login
)
select c.cohort_month,
(extract(year from age(a.active_month, c.cohort_month)) * 12
+ extract(month from age(a.active_month, c.cohort_month)))::int as month_number,
count(distinct a.user_id) as retained
from cohorts c
join activity a
on a.user_id = c.user_id
and a.active_month >= c.cohort_month
group by 1, 2
order by 1, 2;
Run a second query for cohort sizes (select cohort_month, count(*) from cohorts group by 1) and you have everything you need. If SQL isn't your thing, Mode's SQL tutorial covers every piece of this.
In a spreadsheet the idea is the same. Make one row per user per month in which they did the core action, remove duplicates, and add a "months since signup" column. Then a COUNTIFS per cell (same function in Google Sheets) counts users for each signup month and month number.
Two traps here. Count distinct users per period, not events, or one enthusiastic customer will hold your curve up on their own. And use time since signup, not calendar months. "Active in March" mixes people in their first week with people in their second year, and that line means nothing.
Step 3: How do you turn cohorts into a table?
Divide each count by its cohort's starting size and you get the classic cohort triangle. Each row is a signup month. Each column is months since signup. It's a triangle because younger cohorts haven't lived long enough to fill the right-hand columns.
Here's the example dataset I'll use for the rest of the post. It's invented, but it has the shape of a typical early-stage SaaS product: six monthly cohorts of a few hundred users each.
Signup month
Users
M0
M1
M2
M3
M4
M5
M6
Jan
410
100%
58%
46%
41%
39%
38%
38%
Feb
380
100%
59%
47%
42%
40%
39%
·
Mar
450
100%
61%
49%
44%
43%
·
·
Apr
520
100%
63%
52%
47%
·
·
·
May
490
100%
64%
52%
·
·
·
·
Jun
540
100%
66%
·
·
·
·
·
Weighted average
2790
100.0%
62.2%
49.5%
43.9%
40.7%
38.6%
37.6%
Read across a row and you see one cohort ageing. Read down a column and you see whether newer cohorts are doing better or worse at the same age. In this example every column gets darker toward the bottom, so something improved between January and June. I cover reading the table itself in how to read a cohort retention chart and building one in more depth in the cohort analysis guide. What matters here is the bottom row, because that's your curve.
Get weekly churn reduction tips.
No spam, unsubscribe anytime.
You're in.
Check your inbox shortly.
Step 4: How do you average cohorts into one curve?
This is the step where most curves go wrong, and it goes wrong silently.
The right way: for each column, add up the retained users across only the cohorts that have reached that column, and divide by the combined starting size of those same cohorts. Month 6 in the example has only January in it, so month 6 is January's number: 154 out of 410, or 37.6%.
The common wrong way: divide every column by the total of every cohort. Month 6 then becomes 154 out of 2,790, which is 5.5%. June's 540 users get counted as churned in month 6 even though month 6 hasn't happened for them yet.
Same data. One line says you keep nearly 38% of users after six months. The other says you're losing nearly everybody. It's an easy bug to ship, because a spreadsheet formula that divides by a fixed total looks perfectly reasonable, and a team looking at the orange line will go hunting for an engagement problem that isn't there. What they actually have is a denominator problem.
If your curve heads to zero, check the denominator before you check the product.
Two smaller decisions here:
Weight by cohort size. Add up users, then divide, rather than averaging the percentages. Otherwise a cohort of 40 counts as much as a cohort of 4,000. In this example the two methods land within half a point of each other. When they don't, a small cohort is behaving strangely, and that's worth a look on its own.
Know that the tail is your oldest customers only. The right-hand end of the averaged curve is built from your earliest cohorts, because nobody else has got there yet. If your product has improved since, the tail understates where you'll end up. This is a cousin of survivorship bias, and I wrote up the other ways it distorts cohort charts in survivorship bias in cohort retention charts.
Step 5: How should the chart itself look?
Less design, more honesty. My rules:
X-axis is periods since signup, starting at 0. Never calendar dates.
Y-axis runs 0 to 100%, fixed. A y-axis that starts at 30% makes a gentle slope look like a cliff, and a plateau at 38% look like a disaster.
Period 0 is 100% by definition when cohorts are defined by signup. If you define month 0 as "did the core action in the signup month" instead, say so on the chart, because the whole line shifts down.
Use a line, not bars. The shape is the point, and lines show shape.
Stop or mark the line where it gets thin. I stop trusting a point once it rests on fewer than about 100 users or a single cohort. Label how many cohorts sit under the last few points, or fade them out.
Bounded, not "on or after". Most analytics tools let you count a user as retained in month 3 if they were active in month 3 or any month after it. That curve can only go down, so it can never show you people coming back. Use the strict version, "active in exactly that period", for the shape. Mixpanel and PostHog both document their options, and they're worth reading before you trust a default.
Plot your own retention curve
Paste your cohort counts below, one cohort per line: a label, the number of users who started, then how many were retained in period 1, period 2 and so on. The example data is already loaded. It runs entirely in your browser, nothing is sent anywhere.
Paste your cohorts, get your curve
Format per line: label, users at start, retained in period 1, period 2, ... Commas or tabs both work, so you can paste straight from a spreadsheet.
62%
still active in period 1
38%
where the curve ends
Flat-ish
shape of the tail
Where these numbers come from: for each period, the plotter adds up the retained users of every cohort that has a value for that period and divides by the starting users of those same cohorts. That's the weighted average from step 4, and it ignores cohorts that haven't reached the period yet instead of counting them as zero. Tick "show the wrong average" to see the version that divides by every cohort. Period 0 is 100% because cohorts are defined by when people started. The shape verdict looks at the average change per period across the last three points of the line: rising by more than half a point a period is a smile, within a point either way is flat, losing one to three points a period is flat-ish, and anything steeper is still sloping toward zero. The note under the cards tells you how many cohorts and users the last point rests on, because a flat tail built on one small cohort isn't a finding yet. It can't tell you whether you picked the right core action or rhythm. That's step 1, and it matters more than anything the plotter does.
Step 6: What do you plot on top of the average?
The average curve answers "is this a good business?" It can't answer "is it getting better?" or "for whom?" Reforge splits the analysis into three levels, and each level is a different chart.
Level 1: The shape of the average
Four shapes cover almost everything. A line still sloping toward zero means you'll eventually lose every cohort. Flat-ish is a gentle slope you can probably fix with engagement and resurrection work. Flat means you keep a stable share of every cohort forever. A smile, where the line dips and then rises, means people come back and use you more over time, which you mostly see with network effects or expansion. The four shapes are explained in detail on the retention curve simulator, which lets you play with each.
For what "good" looks like, I'd use benchmarks carefully. The Reforge material gives rough plateau ranges: about 60% for B2C social, 35 to 40% for B2C productivity, 25 to 40% for B2C subscription commerce, 80 to 90% for B2B enterprise, around 75% for B2B mid-market and 50 to 60% for very small businesses. Lenny Rachitsky's survey of what good retention looks like lands in similar territory. Treat these as a sense check. The better test is whether your plateau, multiplied by how many people you can reach and what each is worth a year, adds up to the business you want. You can check where your churn sits against peers with Retention Rank.
Level 2: Each cohort as its own line
Plot every cohort row as its own line on the same axes. This is the chart I look at first.
Three questions to ask of it, straight from the Reforge method:
Are newer cohorts above or below older ones? Above means the product, the onboarding or the customer mix is improving. Below means something got worse, and a new acquisition channel is the usual suspect.
Where does the gap open? If the lines split in period 1 and then run parallel, as they do here, the change happened in activation. If they start together and drift apart later, it's engagement. That tells you which team owns the fix, and whether the activation milestones playbook or the sticky features playbook is the right next step.
Is the decline speeding up or slowing down? Work out each cohort's average drop per period. If newer cohorts fall faster in their later periods than older cohorts did at the same age, you have a problem that the averaged curve will only show you months from now.
Watch for outliers too. One cohort sitting far above or below the rest usually has a cause you can name: a launch, a pricing change, a big customer who brought their team, a promo that pulled in the wrong people. Find out what was different. It's often the cheapest lesson you'll get.
Level 3: Segments as separate lines
Then cut the same curve by the things you can act on. Reforge lists eight common cuts: persona (role, company size), acquisition source, device or platform, feature usage, geography, timing such as day of week or season, engagement depth and pricing tier. Plot each segment as its own line on one chart and look for the pair that sits furthest apart.
Be careful with what the gap means. A segment that retains better might do so because of who they are rather than anything you did, and an average across segments can even point in the opposite direction to every segment inside it (that's Simpson's paradox, and retention data is a classic place to meet it). Segment curves tell you where to look. An experiment tells you what works.
What are the most common mistakes when plotting retention curves?
In rough order of how much damage they do:
Counting young cohorts as zero. The denominator bug from step 4. Turns a plateau into a slide.
Measuring logins. Gives you the highest first-month number and the least useful line.
The wrong rhythm. Daily retention for a weekly product, or monthly for a daily one.
Calendar periods instead of time since signup. Mixes brand-new users with two-year veterans in every point.
Counting events, not distinct users. One heavy user holds the line up.
A truncated y-axis. Makes every slope look dramatic.
Trusting the tail. The last few points rest on your oldest, smallest cohorts. Mark them.
Only ever looking at the average. It hides whether you're improving, and for whom.
What to do this week
Pick your core action and rhythm with the 28-day histogram. Run the cohort query. Paste the counts into the plotter above with "show the wrong average" ticked, and check which of the two lines your current dashboard looks like. If it's the orange one, you've just learned something more useful than anything else on this page.
Then plot the cohorts as separate lines and find where the gap opens. That single chart tells you whether to spend the next quarter on activation or engagement, which is otherwise a guess. If you want a second opinion on where your biggest leak is before you dig into data, the free 60-second churn health check asks a few questions and points you at it.
Decide what retained means, average honestly, then stop looking at the average. The cohort lines are where the decisions are.
Answers to the questions I get most often about this topic.
What is a retention curve?
A retention curve is a line chart of the share of a group of users who are still doing your core action N periods after they started. The x-axis is time since signup (days, weeks or months), the y-axis is the percentage still active, and the line usually starts at 100%. Its shape tells you more than any single churn number: a line that flattens means you keep a stable share of every cohort, and a line that keeps sliding means you eventually lose everyone.
How do I plot a retention curve in Google Sheets or Excel?
Make one row per user per period in which they did the core action, with their signup period and the number of periods since signup. Count distinct users for each signup period and each period number with COUNTIFS, divide each count by the cohort size, and you have a cohort table. For the curve, add up the retained users in each column and divide by the combined size of only the cohorts that have reached that column. Plot that row as a line chart with the y-axis fixed from 0 to 100%.
Why does my retention curve go to zero?
Check the averaging before you blame the product. The most common cause is dividing each period by the size of every cohort, including cohorts too young to have reached it, which counts users who simply have not had the time as churned. Average each period only over cohorts that have reached it. If the curve still heads to zero after that, check that you are measuring on the right rhythm, since a weekly product measured daily also looks like it is dying.
Should I use a weighted or unweighted average across cohorts?
Weighted, by cohort size: add up the retained users and divide by the total starting users of the cohorts included. An unweighted average of percentages lets a cohort of 40 users count as much as one of 4,000. In most products the two land within a point or two of each other, and when they do not, that gap is telling you a small cohort is an outlier worth looking at on its own.
Should I measure daily, weekly or monthly retention?
Match the natural rhythm of the job. Take paying customers and count how many of the last 28 days each one did the core action. If most cluster at 20 or more days you are a daily product, around 3 to 7 days is weekly, and 1 or 2 days is monthly. Measuring a weekly product on daily retention makes a healthy product look broken, and measuring a daily product monthly hides problems for weeks.
What should count as retained: a login or something else?
The simplest action that shows the customer got value, not a login. Plot curves for two or three candidates, such as logged in, created a report and shared a report, and pick the one with the flattest, highest tail. Logins often start highest and keep sliding, because people check in without getting anything done. Avoid combining several actions into one metric, since teams then push whichever action is easiest.
How many users do I need for a reliable retention curve?
There is no magic number, but each point on the line should rest on enough people that one or two users changing their behaviour does not move it visibly. As a working rule I stop trusting a point once it rests on fewer than about 100 users or a single cohort, and I either mark it or cut the line there. Early-stage products with small monthly cohorts are often better served by weekly cohorts with monthly periods, or by grouping two months together.
What is the difference between a cohort table and a retention curve?
The cohort table is the raw grid: one row per signup cohort, one column per period, each cell the share of that cohort still active. The retention curve is a summary of that grid, usually the weighted average of each column drawn as one line. The table shows you whether newer cohorts are doing better or worse. The curve shows you the overall shape. You need both, and overlaying the individual cohort rows as separate lines gives you the best of the two.
Founder of ChurnTools. I spend my time studying how SaaS companies lose customers and building tools to help them stop. Previously worked in SaaS growth and retention across multiple B2B products. I also write about growth and answer-engine optimization (AEO) at growthpigeon.com.
One tap, no signup. It builds your retention map as you read.
You have flagged enough to be worth costing out. The Health Check scores the same
dimensions properly and tells you which gap is losing you the most money.
Knowing the number is not the same as knowing the cause
A calculator tells you how much is leaving. It cannot tell you which part is failed payments,
which part is people who never activated, and which of the two is cheaper to fix.
I work that out on your actual data and send back three fixes ranked by what each one is worth,
within 10 working days.
✓ Voluntary and involuntary churn, split and costed