Most SaaS companies track onboarding with a dedicated analytics tool Mixpanel, Amplitude, Segment and those tools are genuinely useful for tracking frontend events. But they have a blind spot: anything that happens in your backend database. Subscription plan assignments, feature flag activations, account configurations, integrations connected the events that actually predict whether a user will stick around are often stored in your database, not your event stream.
This guide is about using your database to understand onboarding performance: what activation looks like, how to measure it, and how to identify where users fall off.
Why Database-Level Onboarding Data Is More Reliable
Event tracking tools capture what users click and view. Your database captures what users actually do: created a project, invited a teammate, connected an integration, ran a query, completed a payment.
Those are different kinds of signals. A user can click through an entire onboarding checklist without actually using your product. A user who has never clicked the onboarding checklist but has set up three integrations is deeply activated.
The distinction matters because activation rates calculated from click events and activation rates calculated from backend database events often look very different. One measures exposure to your onboarding UI. The other measures adoption of your core product.
For most B2B SaaS products, the database-level signal is the better predictor of long-term retention.
Defining Your Activation Criteria in the Database
The first step is agreeing on what "activated" means for your product and encoding it as a database query.
A few examples:
Project management tool:
-- Activated = created at least one task AND invited at least one teammate
SELECT
u.id,
u.email,
u.created_at,
COUNT(DISTINCT t.id) AS tasks_created,
COUNT(DISTINCT tm.invitee_id) AS teammates_invited
FROM users u
LEFT JOIN tasks t ON t.creator_id = u.id
LEFT JOIN team_invitations tm ON tm.inviter_id = u.id
WHERE u.created_at >= '2026-01-01'
GROUP BY u.id, u.email, u.created_at
HAVING COUNT(DISTINCT t.id) >= 1 AND COUNT(DISTINCT tm.invitee_id) >= 1;Analytics platform:
-- Activated = connected at least one data source within 7 days of signup
SELECT
u.id,
u.email,
u.created_at,
MIN(ds.created_at) AS first_connection_date,
EXTRACT(EPOCH FROM (MIN(ds.created_at) - u.created_at)) / 86400 AS days_to_activation
FROM users u
JOIN data_source_connections ds ON ds.user_id = u.id
WHERE ds.created_at <= u.created_at + INTERVAL '7 days'
GROUP BY u.id, u.email, u.created_at;E-commerce SaaS:
-- Activated = published first product listing
SELECT
u.id,
u.email,
MIN(p.published_at) AS first_listing_date,
EXTRACT(EPOCH FROM (MIN(p.published_at) - u.created_at)) / 3600 AS hours_to_activation
FROM users u
JOIN products p ON p.seller_id = u.id
WHERE p.status = 'published'
GROUP BY u.id, u.email, u.created_at;The specific criteria depend on your product. The principle is the same: pick the 1-2 backend actions that most strongly predict a user becoming a paying or long-term customer. If you don't know what those are yet, start with your best guess and validate it against retention data.
Measuring Activation Rate Over Time
Once you have your activation definition, you can track the rate week over week:
WITH weekly_signups AS (
SELECT
user_id,
DATE_TRUNC('week', created_at) AS signup_week
FROM users
),
activated AS (
SELECT DISTINCT user_id
FROM tasks -- or whatever your activation event table is
WHERE created_at IS NOT NULL
)
SELECT
ws.signup_week,
COUNT(DISTINCT ws.user_id) AS signups,
COUNT(DISTINCT a.user_id) AS activated_users,
ROUND(100.0 * COUNT(DISTINCT a.user_id) / COUNT(DISTINCT ws.user_id), 1) AS activation_rate_pct
FROM weekly_signups ws
LEFT JOIN activated a ON ws.user_id = a.user_id
GROUP BY ws.signup_week
ORDER BY ws.signup_week;Or with AI for Database, you describe this in plain English:
"Show me weekly signup-to-activation rate for the last 12 weeks. Activation means a user created at least one project."
The system writes and runs the query, returns a table, and you can follow up immediately:
"Which week had the highest activation rate? What changed around that time?"
Finding Your Onboarding Drop-off Points
Activation rate as a single number is useful. Understanding where users drop off is where you can actually take action.
Most onboarding flows have a sequence of steps signup → email verification → profile setup → core feature use → invite teammates. Each step has a conversion rate. If users are completing step 3 but abandoning before step 4, you know exactly where to focus.
If these steps are recorded in your database (common in products that track onboarding completion as a feature), you can query the funnel directly:
SELECT
MAX(CASE WHEN step = 'email_verified' THEN 1 ELSE 0 END) AS completed_email_verification,
MAX(CASE WHEN step = 'profile_completed' THEN 1 ELSE 0 END) AS completed_profile,
MAX(CASE WHEN step = 'first_project_created' THEN 1 ELSE 0 END) AS completed_first_project,
MAX(CASE WHEN step = 'teammate_invited' THEN 1 ELSE 0 END) AS completed_invite,
COUNT(DISTINCT user_id) AS total_users
FROM onboarding_events
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY ROLLUP(completed_email_verification, completed_profile, completed_first_project, completed_invite);If your onboarding steps aren't tracked as explicit events, you can infer them from action tables:
SELECT
COUNT(DISTINCT u.id) AS total_signups,
COUNT(DISTINCT e.user_id) AS verified_email,
COUNT(DISTINCT p.user_id) AS set_up_profile,
COUNT(DISTINCT pr.created_by) AS created_first_project,
COUNT(DISTINCT tm.inviter_id) AS invited_teammate
FROM users u
LEFT JOIN email_verifications e ON e.user_id = u.id
LEFT JOIN user_profiles p ON p.user_id = u.id AND p.completed = true
LEFT JOIN projects pr ON pr.created_by = u.id
LEFT JOIN team_invitations tm ON tm.inviter_id = u.id
WHERE u.created_at >= CURRENT_DATE - INTERVAL '30 days';Segmenting Onboarding Performance by Acquisition Channel
A common mistake is treating all new users as a single cohort. Your organic search users, your paid acquisition users, and your referral users often behave very differently during onboarding.
If your users table includes an acquisition_source or utm_source column (populated from signup parameters), you can segment activation rates with one additional line:
SELECT
u.acquisition_source,
COUNT(DISTINCT u.id) AS signups,
COUNT(DISTINCT a.user_id) AS activated,
ROUND(100.0 * COUNT(DISTINCT a.user_id) / NULLIF(COUNT(DISTINCT u.id), 0), 1) AS activation_rate
FROM users u
LEFT JOIN (
SELECT DISTINCT user_id FROM projects -- activation event
) a ON a.user_id = u.id
WHERE u.created_at >= CURRENT_DATE - INTERVAL '60 days'
GROUP BY u.acquisition_source
ORDER BY activation_rate DESC;If you find that referral users activate at 65% while paid social users activate at 22%, that's not just a marketing insight it tells you that your onboarding experience might be poorly matched to users arriving with low product context. The fix might be in onboarding, not in ad targeting.
Time-to-Activation: The Signal Most Teams Miss
Activation rate tells you what percentage of users complete your key action. Time-to-activation tells you how quickly they do it and that second number is often a stronger predictor of long-term retention.
A user who creates their first project in 2 hours will almost always retain better than a user who creates their first project on day 12. The latter user probably had to be nudged, reminded, or re-engaged. Their activation was externally prompted, not internally motivated.
SELECT
CASE
WHEN hours_to_first_project < 1 THEN 'Within 1 hour'
WHEN hours_to_first_project < 24 THEN 'Within 24 hours'
WHEN hours_to_first_project < 72 THEN '1-3 days'
WHEN hours_to_first_project < 168 THEN '3-7 days'
ELSE 'After 7 days'
END AS activation_speed,
COUNT(*) AS user_count
FROM (
SELECT
u.id,
EXTRACT(EPOCH FROM (MIN(p.created_at) - u.created_at)) / 3600 AS hours_to_first_project
FROM users u
JOIN projects p ON p.created_by = u.id
WHERE u.created_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY u.id, u.created_at
) activation_times
GROUP BY activation_speed
ORDER BY MIN(hours_to_first_project);If you then join this to a 30-day retention column, you'll typically find that the "within 1 hour" segment retains at dramatically higher rates. That gives you a clear north-star metric for your onboarding team: reduce median time-to-activation.
Setting Up Automated Onboarding Alerts
One of the most practical things you can do with your onboarding data is set up an automated alert that fires when something goes wrong.
A good example: an alert that triggers when week-over-week activation rate drops by more than 10 percentage points. This catches a broken integration, a confusing UI change, or a broken signup flow before it compounds.
With AI for Database's action workflows, you define a condition like:
"When this week's activation rate is more than 10% below last week's activation rate, send a Slack message to #product-alerts."
No stored procedures. No database triggers. No cron jobs. The system monitors the condition on a schedule and fires the alert automatically.
This is the kind of monitoring that used to require a data engineer to set up and then maintain whenever the schema changed.
Building a Shared Onboarding Dashboard
Onboarding metrics shouldn't live in one person's SQL query. They should be visible to product, growth, and customer success teams in a format they can actually use.
With AI for Database, you can build a dashboard that shows:
Set the dashboard to refresh daily. Any team member can open it without running a query or asking the data team.
They can also ask follow-up questions in plain English: "Show me activated users from the last 7 days who haven't invited a teammate yet." That's a growth lever activated users who haven't gone through the collaborative step are prime candidates for an in-app nudge.