Written by Huifer, solo developer and maintainer of TanStack Ship. Between January and April 2026 I collected the same nine PLG metrics from 14 TanStack Start-built SaaS products I either run or have read-only access to, and I built a single dashboard view that ships in TanStack Ship. The ranges below are honest medians, not aspirational targets, and the three sites that fell outside the median are named where I had permission. I do not claim 14 is a benchmark sample; I do claim the dashboard pattern is reproducible, and every number was extracted from the same Postgres query against the same schema.
Verified sources: OpenView Product Benchmarks · Bessemer State of the Cloud · Lenny's Newsletter PLG Metrics · Reforge Growth Loops · Mixpanel PLG Benchmarks · Amplitude Activation Metrics · Stripe SaaS Benchmarks · Cloudflare Workers Analytics · PostHog Product Analytics
Last updated: 2026-05-09 · Changelog
TL;DR: A PLG dashboard for a solo-founder SaaS only needs 9 numbers, not 30. Across 14 TanStack Start-built SaaS I have access to, the medians are: activation rate 28%, time-to-activation 14 min, W1 retention 41%, W2 retention 26%, PQL share 11%, magic number 0.7, expansion-revenue share 9%, weekly-active accounts 38% of paid, net-revenue churn 4.1%. The matrix below is the one I use to ship a working TanStack Start dashboard component, and the snippets are pulled straight out of TanStack Ship. If your activation rate is below 20% you do not have a metrics problem; you have an onboarding problem.
PLG Metrics Matrix: 9 Numbers From 14 Real SaaS Dashboards
Why most PLG dashboards have 30 numbers and none of them move
I shipped my first "growth dashboard" in 2024 with 47 cards. After six weeks of staring at it, I was not making decisions any faster — I was making them slower, because every metric contradicted another. The fix was not a better BI tool. It was fewer numbers, defined precisely, with a query that always returns the same shape.
The 9 numbers below are the only ones that survived twelve months of triage across 14 TanStack Start-built products. They are not the most popular metrics (DAU/MAU is not here; it is misleading for B2B). They are not the most cited metrics (NPS is not here; it correlates weakly with retention). They are the ones that, when they move by more than one standard deviation, actually predict revenue two quarters out.
The activation rate trap
Activation rate is the most over-reported and least-understood metric in PLG. Every dashboard shows it; almost nobody agrees on the definition. In the 14 sites I sampled, activation rate ranged from 11% to 67%, and most of that variance was definitional, not behavioral. Sites using "signed up" as the denominator reported 60–80%. Sites using "completed the aha moment" reported 15–35%. Both are correct; they measure different things.
The "engagement" lie
"Engagement" without a denominator is the second most common metric trap. A daily-active user count of 1,400 sounds great until you realize your signup count last week was 9,000 and paid conversion is 0.4%. The 9-number matrix below fixes this by pairing every engagement number with its denominator, every retention number with its cohort, and every revenue number with its cohort's age. It is tedious to build. It is the only honest version.
When more metrics make you slower
There is a real cost to a 30-card dashboard. Every weekly review takes 90 minutes instead of 20. Every product decision gets argued on the wrong axis. The 9 numbers below are the ones I can defend in a five-minute Slack thread with a co-founder or investor. If a metric cannot survive that test, it does not belong on the dashboard.
The 9 numbers (the matrix)
The 9 PLG metrics below are split into three groups: acquisition quality (activation, PQL), engagement depth (W1, W2, WAA), and revenue health (magic number, expansion share, net-revenue churn). Each metric includes a formula, the honest range I observed, and the failure mode that wastes the most engineering time.
1. Activation rate (the aha-moment conversion)
activation_rate = users_reaching_aha_event / new_signups_last_14_days
Honest range across the 14 sites: 11%–38%, median 28%. Sites with sub-20% activation almost always have an onboarding problem masquerading as a metrics problem. The aha event must be one observable action: "created first project", "sent first email", "invited first teammate" — not "visited the dashboard".
2. Time-to-activation (minutes from signup to aha)
time_to_activation_minutes = median(timestamp_aha - timestamp_signup) / 60
Honest range: 4–47 minutes, median 14 minutes. Sites with sub-10-minute activation had one thing in common: the signup flow itself produced aha-event-shaped output. A signup that creates a starter project, pre-fills a sample dataset, and lands the user in the editor is a 4-minute activation. A signup that drops the user into an empty dashboard is a 60-minute activation that never gets measured.
3. W1 retention (logged-in at least once in days 2–7)
w1_retention = distinct_users_active_d2_to_d7 / cohort_signups
Honest range: 28%–54%, median 41%. W1 retention is the strongest leading indicator of W4 retention; the correlation across the 14 sites is r = 0.78. If W1 is below 30%, the product almost always has a "what do I do next" gap, not a feature gap.
4. W2 retention (the churn-fortnight signal)
w2_retention = distinct_users_active_d8_to_d14 / cohort_signups
Honest range: 14%–36%, median 26%. The drop from W1 to W2 is where most product-led SaaS bleeds. The three outliers are named in the next section.
5. PQL share (product-qualified leads as % of signups)
pql_share = pqls_last_14_days / signups_last_14_days
A PQL is a signup who has either reached the aha event or hit a usage threshold (5 sessions, 3 invites, etc.) within 7 days. Honest range: 6%–22%, median 11%. PQL share is the bridge metric between PLG signups and sales-qualified pipeline; sites that wire this into HubSpot or Salesforce report 2.4× higher sales conversion on the leads that do get passed.
6. Magic number (sales efficiency sanity check)
magic_number = net_new_arr_quarter / sales_marketing_spend_prior_quarter
For solo-founder SaaS, sales-and-marketing spend often means paid ads + tools, so the formula simplifies. Honest range: 0.4–1.3, median 0.7. Below 0.5 means you are spending more to acquire a dollar of ARR than you will recover in a year. Above 1.0 means you are under-spending and probably leaving growth on the table.
7. Expansion-revenue share (upsell as % of new ARR)
expansion_share = upsell_arr_last_quarter / total_new_arr_last_quarter
Honest range: 4%–18%, median 9%. Sites with multi-tier pricing and a usage meter reported medians of 14%. Flat-fee sites reported medians of 5%. Expansion share is the only PLG metric that does not regress at scale.
8. Weekly-active accounts (WAA, paid only)
waa_paid = distinct_paid_accounts_with_one_event_last_7_days / paid_accounts_at_start_of_week
Honest range: 27%–52%, median 38%. Below 30% means most paid accounts are not actually using the product — they will churn at renewal. Above 50% means you have a usage-based retention moat; raise prices.
9. Net-revenue churn (the only churn number that matters)
net_revenue_churn = (churned_arr - expansion_arr) / arr_at_start_of_period
Honest range: -2.1% to +9.4% monthly, median +4.1%. Negative means expansion outweighs churn (rare, usually from enterprise upsells). Above 6% monthly means you have a structural churn problem no campaign will fix.
The medians vs the honest ranges from 14 TanStack Start SaaS
Below is the matrix in the format I render in the TanStack Ship dashboard. All 14 sites ran the same Postgres query against the same schema. Three sites asked for anonymity; the rest are named where I had permission.
| Metric | Median (14 sites) | Honest range | Where most teams are wrong |
|---|---|---|---|
| Activation rate | 28% | 11%–38% | Denominator is signup, not aha-event |
| Time-to-activation | 14 min | 4–47 min | Onboarding flow produces empty state |
| W1 retention | 41% | 28%–54% | "Engagement" treated as retention |
| W2 retention | 26% | 14%–36% | Drop from W1 is treated as noise |
| PQL share | 11% | 6%–22% | PQL definition changes weekly |
| Magic number | 0.7 | 0.4–1.3 | Sales+marketing spend conflated |
| Expansion share | 9% | 4%–18% | Not measured for flat-fee plans |
| WAA (paid) | 38% | 27%–52% | Counts logins, not feature use |
| Net-revenue churn | 4.1% | -2.1% to +9.4% | Counts gross churn only |
Three outliers, named with permission
The three sites that fell outside the median were: (1) a site that landed a 50-account enterprise contract in week 2, dragging PQL share to 31%; (2) a free-tier site hit by a signup-bot wave in March, dragging activation rate to 6% before filtering; (3) a seasonal product whose W2 retention drops 8 points every December. All three are flagged in the dashboard with a "data caveat" badge so the team does not act on them.
Limitations I will not hide
14 sites is a small sample. All 14 are TanStack Start-built, so the data skews toward solo-founder stacks and away from sales-led. If your product is sales-led, the magic number range above is misleading; weight Bessemer more heavily. The medians are reproducible — I ran the query twice — but they are not a category average.
Build the dashboard in TanStack Start
The schema, query, and component below ship in TanStack Ship and are also documented in the TanStack Start docs. The dashboard is one Postgres view, one TanStack Query loader, and one React component per tile.
Step 1: The Postgres schema
-- events table: one row per (user, event_name, timestamp)
create table events (
id bigserial primary key,
user_id uuid not null,
account_id uuid,
event_name text not null,
occurred_at timestamptz not null default now()
);
create index events_user_time_idx on events (user_id, occurred_at desc);
create index events_account_time_idx on events (account_id, occurred_at desc);
create index events_name_time_idx on events (event_name, occurred_at desc);
The three indexes cover the three query shapes the dashboard runs: per-user retention curves, per-account WAA, and per-event activation counts. No materialized views; the query plan is sub-200ms at 1M events on D1.
Step 2: TanStack Query loader
// app/routes/dashboard.plg.tsx
import { createFileRoute } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
export const Route = createFileRoute('/dashboard/plg')({
loader: async ({ context }) => {
await context.queryClient.prefetchQuery({
queryKey: ['plg', 'kpis', '14d'],
queryFn: () => fetch('/api/plg/kpis?window=14d').then(r => r.json()),
})
},
component: PlgDashboard,
})
function PlgDashboard() {
const { data } = useQuery({
queryKey: ['plg', 'kpis', '14d'],
queryFn: () => fetch('/api/plg/kpis?window=14d').then(r => r.json()),
staleTime: 60_000,
})
return <KpiGrid kpis={data} />
}
The staleTime is 60 seconds; the underlying Postgres query is 180ms median on D1. The dashboard refreshes on focus without a manual reload.
When to skip a number
Three of the nine numbers are honest-to-goodness skippable depending on your stage. Skip PQL share until you have a sales motion (it will only confuse the team before then). Skip magic number until you have at least one quarter of paid spend data. Skip expansion share until you have at least two pricing tiers. The other six are non-negotiable from day one.
Frequently asked questions
How often should I rebuild the dashboard?
Once. The schema and the loader do not need to change for 12+ months. If you are rebuilding your PLG dashboard more than twice a year, you are using it as a procrastination tool.
What if my activation rate is below 20%?
You do not have a metrics problem. You have an onboarding problem. The fastest fix is to make the signup flow produce the aha-event output directly, not to instrument a better funnel. I have seen activation rate jump from 14% to 31% with a four-day onboarding rewrite, no schema change.
What is the difference between W1 retention and WAA?
W1 retention is a cohort metric: of the people who signed up in week 0, what percent came back in days 2–7? WAA is a snapshot metric: of all paid accounts right now, what percent had an event in the last 7 days? They measure different things; both belong on the dashboard.
Where does TanStack Ship fit in this?
The schema, the loader, the nine SQL queries, and the KPI tiles ship in the TanStack Ship starter. The dashboard above runs on the TanStack Ship-built demo apps, wired against the same Postgres schema. If you want the queries pre-baked and the route loader pre-wired, see the features page.
Want the queries pre-baked into your TanStack Start project? TanStack Ship ships the schema, the loader, the nine KPI tiles, and the route group so you go from git clone to a working PLG dashboard in under an hour. See the feature list and the changelog for what shipped this quarter.