Onboarding Email Sequence: Build It on Events, Not Days
Summary
An onboarding email sequence should be built around one activation event and send each email because of a user signal, not a calendar day. Start with a welcome email, add a 24-hour nudge that only fires if the first action is missing, define exit rules before you write copy, and measure click-to-activate against a holdout group instead of open rate, which mail privacy features inflate.
An onboarding email sequence works when it reacts to what a new user did, not to how many days have passed. Build it around one activation event, send each email because of a signal, and give every email an exit condition. A fixed Day 1, Day 3, Day 7 schedule is the fallback, not the design.
Most teams do the reverse. They write five emails, attach delays, and ship. Six weeks later activation has not moved and nobody can say which email is responsible.
Start from the activation event, not the welcome email
The sequence exists to move a signup to one measurable action. Pick it before you write a word of copy. "Created a project" or "sent first API request" qualifies. "Logged in" does not.
Define the window too. Our default is activation within 14 days of signup, counted per signup cohort. Without the window you cannot compare two versions of the sequence.
Then work backwards. List the steps a user must complete to reach that event, and give each step one email at most. If a step has no email, the user either does it alone or you accept the drop-off.

Skip the "tour of features" email. It answers a question nobody asked on day two. One email, one action, one link.
What does a minimal sequence look like in practice?
Five emails cover most SaaS products with a trial. This is the shape we see hold up, with the trigger for each.
Welcome: sent on
user.signed_up, within seconds. Confirms the account, names the single first action, links straight to it.First-action nudge: sent 24 hours after signup only if the activation step 1 event has not fired.
Blocker help: sent when a known failure signal appears, such as an invalid API key error or an abandoned import. This is the highest-value email in the set.
Proof email: sent on day 3 to users who started but did not finish. One customer outcome, one number with its context.
Last step push: sent when the user is one event away from activation, or on day 7 as a time-based fallback.
Notice that three of the five are conditional. The welcome email is the only one that goes to everyone.
Welcome emails also get the best open rates you will ever see. Treat that number with suspicion: Apple Mail Privacy Protection preloads images and inflates opens for a large part of your list. Track click-to-activate instead.
Time-based drips fail on the users who matter most
A pure time-based drip sends the day-three email to a user who activated on day one. That user now gets told to do something they already did. It reads as automation, and it is.
It also fails in the other direction. A user who is stuck on step two gets a cheerful feature email, not help. The sequence cannot see the problem, so it cannot respond.
The fix is not complicated, but it needs an event source. Behavioral sequences need three inputs: the event stream, a per-user state, and a rule that checks state before each send.
{
"trigger": "user.signed_up",
"steps": [
{ "id": "welcome", "delay": "0s" },
{ "id": "first_action_nudge", "delay": "24h",
"send_if": "NOT event(project.created)" },
{ "id": "proof", "delay": "72h",
"send_if": "event(project.created) AND NOT event(first_send)" },
{ "id": "last_step", "delay": "7d",
"send_if": "NOT event(activated)" }
],
"exit_when": ["activated", "unsubscribed", "account.deleted"]
}The send_if check runs at send time, not at enrolment time. That distinction matters. If you evaluate the condition when the user enters the flow, you have built a static segment, and the state will be stale by the time the email goes out.
The exit condition is the feature people forget
Every sequence needs a rule that ends it. The obvious one is activation. Two others get missed: unsubscribe from the onboarding stream, and account deletion or trial expiry.
We have seen sequences keep emailing users after they converted to paid. That is an exit condition bug, and it costs you more than a missed open. It teaches the user that your emails are not tied to their account.
Write the exit rules first and test them first. Replay a few real user timelines through the flow in a staging environment and check that each one stops where it should. A sequence with good copy and no exits is worse than a sequence with plain copy and clean exits.

Where the event data comes from
The quality of the sequence depends on the quality of the signal. There are three common sources, and they have different latency and failure modes.
A product analytics pipeline such as Segment forwards events within seconds, but only the events you instrumented. A direct webhook from your backend is the most reliable, because it fires from the code path that does the work. Postgres change data capture sees everything that touches the row, including changes made by admin scripts, which can be a feature or a bug.
Pick one source of truth for the activation event, and document it next to the flow definition so the next engineer does not add a second one. Two sources that disagree by a few minutes will produce emails that contradict the product state. That is how a user gets "Finish setting up" after finishing setup.
Idempotency matters here as well. Event pipelines retry, so the same project.created event may arrive twice. If your sender does not deduplicate by key, the user gets a double send.
Customer.io is built around this model: it ingests events through an API, SDKs or a CDP and triggers from a workflow builder. If you already run on a different stack, the same pattern works with any sender that accepts a trigger and evaluates conditions at send time.
Transactional or marketing: pick the stream deliberately
Some onboarding emails are transactional in practice. A "your API key is ready" message or an email verification should not wait behind a marketing queue, and it should not share a sending reputation with a promotional blast.
Postmark makes this split a design principle by separating message streams onto different infrastructure. The reasoning is sound even if you do not use it: a bad promotional send should never delay a password reset.
Our rule is simple. If the user cannot proceed without the email, it goes on the transactional stream. If the email is encouragement, it goes on the lifecycle stream, with an unsubscribe link that only affects that stream.

Does a developer-first sender change the build?
It changes the starting point. With an API-first sender, the sequence logic lives in your code or in a small worker, and the provider only delivers. You get version control, tests and code review for your flows, and you lose the visual builder.
Resend takes this route, with a REST API, official SDKs and React Email templates. For a team that already treats emails as components, that is a reasonable fit. For a growth team that wants to edit copy without a deploy, it is friction.
Be honest about who edits the sequence. If the answer is "growth, weekly", a workflow builder is the right call, even if engineers dislike it. If the answer is "engineering, per release", keep it in code.
Measure click-to-activate, not opens
Open rate is a weak signal for this job. Mail privacy features inflate it, and an open does not mean the user did anything. Three numbers tell you more.
Click-to-activate: of the users who clicked a given email, how many reached the activation event within 24 hours.
Trigger latency: the time between the event and the send. For a blocker email, anything beyond a few minutes loses the moment.
Activation rate against a holdout: hold back a small group of signups from the sequence and compare their 14-day activation to the rest.
The holdout is the only way to know the sequence works. Without it, you are crediting the emails for activation that would have happened anyway.
We do not quote a benchmark activation rate here, because the published ones come from vendors with different definitions. Measure your own baseline first. Then change one email at a time.
Should you build one sequence or several?
Split by entry condition, not by persona labels. A user who signed up from an invite has a different first action than one who signed up alone. A user who imported data has already crossed a line the others have not.
Two or three entry paths are usually enough. More than that and the maintenance cost beats the lift, because every path needs its own exits and tests.
An all-in-one platform can reduce the setup work when the team is small. Brevo bundles email, SMS and a CRM under one login, which suits teams that do not want to wire an event pipeline yet. The trade-off is that the marketing dashboard sits at the center, and sub-second triggers are not what it is optimised for.
What we would ship first
Write the activation event and the 14-day window on one line. Build the welcome email and the 24-hour nudge with a send_if check and a clean exit. Add a holdout of 5 to 10 percent from day one.
Leave the proof email and the last-step push until you have two weeks of data. Add the blocker email as soon as you can name the most common failure in your logs. Which failure signal in your product would you wire up first?