Skip to main content
Lifetime license included with every purchase
n8n workflowsonboarding automationdrip sequenceSaaS retention

Build a Self-Hosted Onboarding Drip Sequence in n8n

Build an n8n onboarding drip sequence on a Schedule Trigger and Wait nodes, with VIP branching and a re-entrancy guard that stops double-sends.

Nn8n Marketplace Team·July 4, 2026·Updated July 4, 2026·8 min read

New users decide whether your product is worth keeping in the first week. A good onboarding drip walks them from signup to first value before they go quiet. The catch: most n8n onboarding drip sequence tutorials hand you a HubSpot sequence node or a Kit integration and call it done. That works until you want the logic on your own self-hosted n8n, where you own the timing, the branching, and the data.

This walks through the self-hosted version. No third-party sequence engine. Just a Schedule Trigger, a few Wait-or-branch decisions, and a state column that keeps the whole thing honest.

The hard part isn't sending email. It's making sure a contact gets exactly the right step at the right time, once, even when the workflow restarts mid-run.

What you can automate in an onboarding flow

A self-hosted onboarding sequence can cover most of the manual nudging a success team does by hand:

  • Day-0 welcome email with the one action that drives activation
  • Day-2 "have you tried X yet?" check tied to a usage flag
  • Day-5 social proof or a short how-to for the feature people skip
  • VIP branch: a real human intro email for accounts above a revenue threshold
  • Day-9 re-engagement for anyone who hasn't logged in
  • Internal Slack alert when a high-value account stalls
  • A clean exit that marks the contact "onboarded" and stops the drip

The point isn't volume. It's that each branch fires off observed state, not a blind calendar blast.

Why HubSpot-style sequences hide the logic you need

The library templates lean on HubSpot sequences or a Kit drip because those tools hold the timing and branching internally. You drop a contact in, they handle the rest. Fine, until you need a branch the vendor doesn't expose, or you don't want to pay per contact, or you're already self-hosting everything else.

Here's the opinionated take: for onboarding, a Schedule Trigger that re-reads state every run beats the Wait node for anything longer than a few minutes. A Wait node holds the execution in memory (or in the DB, in queue mode). Redeploy n8n, or hit a crash, and a held execution can vanish. The contact silently never gets day 5. A Schedule-driven design has no held state to lose. It asks, every run: who's due, and what did they last get? That question is answerable from the sheet alone.

The onboarding drip pipeline

Schedule Trigger (hourly)
  → Read contacts (Google Sheets / Postgres)
  → Filter: due for next step AND not already sent
  → Switch: route by days-since-signup + VIP flag
  → Send step email (Gmail / SMTP)
  → Write back: last_step, last_sent_at
  → Slack alert if VIP stalled

Every run is idempotent. It reads the world, acts on whoever's genuinely due, and records what it did. Run it twice by accident and nothing double-fires, because the filter already excludes anyone whose last_step matches the step they'd get next.

1. Trigger and read state

Use a Schedule Trigger on an hourly Cron expression rather than "every minute". A trigger that fires every minute will silently drop runs if the previous execution is still in flight, and onboarding doesn't need minute precision. Hourly is plenty.

The Google Sheets node (or a Postgres SELECT) pulls every active contact plus their signup_at, last_step, last_sent_at, and a vip flag. That sheet is your source of truth. No external sequence state to reconcile.

2. Decide who's actually due

A Code node computes days_since_signup and the next_step each contact should be on. Then a filter keeps only rows where the next step is greater than last_step and enough time has passed since last_sent_at. This is the re-entrancy guard. It's the single most important node in the flow.

// Code node: compute eligibility
const now = Date.now();
return items
  .map(({ json }) => {
    const days = Math.floor((now - new Date(json.signup_at)) / 864e5);
    const next = days >= 9 ? 4 : days >= 5 ? 3 : days >= 2 ? 2 : days >= 0 ? 1 : 0;
    return { json: { ...json, days, next } };
  })
  .filter(({ json }) =>
    json.next > Number(json.last_step || 0) &&
    now - new Date(json.last_sent_at || 0) > 12 * 36e5
  );

The 12 * 36e5 is a 12-hour cooldown in milliseconds. It means even a misfire can't push two emails inside half a day. Tune it to your shortest gap.

3. Route by step and segment

A Switch node branches on next (the step) and reads the vip flag. Standard contacts flow down the templated-email path. VIP accounts route to a separate branch that sends a plainer, "reply to me directly" message from a real mailbox. The branch costs you nothing and it's the difference between an enterprise trial feeling automated and feeling handled.

4. Send and record

Each branch ends in a Gmail or SMTP send, then writes last_step and last_sent_at back to the row. Write the state back even if the send is one node away from the trigger. If you send first and the write fails, the next run re-sends. Order matters: send, then immediately record, and let n8n's error workflow catch the rare write failure.

5. Escalate the stalls

For VIP accounts that hit day 9 without a login flag, a Slack node pings the success channel. That's the human-in-the-loop seam. The drip handles the routine nudges; a person handles the account worth saving.

The re-entrancy guard is the whole game

Onboarding drips break in one predictable way: double-sends. Two overlapping Schedule runs, a manual re-trigger during testing, a redeploy mid-execution. Every one of those re-sends step 3 to someone who already got it. Store last_step and last_sent_at per contact, gate every send on them, and the failure mode disappears. It's boring. It's also why your users don't get three identical welcome emails.

Implementation patterns that hold up

Pattern 1: state-in-sheet, not state-in-execution. Keep timing and progress in the contact row, never in a held Wait node. This is what makes the workflow restart-safe. A redeploy loses in-flight executions; it doesn't lose a Google Sheet.

Schedule → Read sheet → Compute next_step → Filter unsent → Send → Write back

Pattern 2: the VIP fork. One Switch output for accounts above a revenue or plan threshold. Route them to human-from email, lighter automation, and a Slack heads-up. Everyone else gets the templated track.

Switch (vip == true) → human-voice email + Slack alert
Switch (vip == false) → templated step email

Pattern 3: the clean exit. When next exceeds your last real step, set a status of onboarded and let the filter exclude them forever after. No zombie contacts looping in the drip.

For teams that also want to gather signal at the end of onboarding, the User Feedback Loop template pairs naturally here: it ingests feedback from a webhook, Google Forms, or Typeform, runs sentiment with OpenAI, and pings the team on Telegram, so the last onboarding step can route an unhappy reply straight to a human.

n8n nodes you'll use most

NodePurpose
Schedule TriggerHourly Cron scan of the contacts sheet
Google Sheets / PostgresRead and write per-contact onboarding state
CodeCompute days-since-signup and the eligibility filter
SwitchBranch by step number and VIP flag
Gmail / SMTPSend each step's email
SlackEscalate stalled high-value accounts

The Schedule Trigger and the Code-node filter do the heavy lifting. The rest is plumbing.

Getting started

  1. Build a contacts sheet with columns: email, signup_at, last_step, last_sent_at, vip, status.
  2. Add a Schedule Trigger on an hourly Cron, not "every minute".
  3. Read the sheet, then add the Code node that computes next and filters on the re-entrancy guard.
  4. Wire a Switch on next and vip; draft one email per step.
  5. After each send, write last_step and last_sent_at back to the row.
  6. Add the Slack escalation branch for stalled VIP accounts.
  7. Test with a throwaway row set to signup_at of five days ago and watch exactly one email fire.
Browse onboarding and retention templates
Skip the build

The Efficient Onboarding & Knowledge Retention System ships this end-to-end: a Google Sheets new-hire trigger sends personalized welcome emails with documents attached, spins up a Notion knowledge-base page with team contacts, assigns Trello onboarding tasks with milestone deadlines, and logs every step back to Sheets for tracking. It's part of The Complete n8n Templates Bundle, a one-time lifetime license to the whole catalog plus every template added later, worth it if you run more than one of these automations.

Get the Onboarding & Knowledge Retention System

Once the drip runs clean, the next gap is usually what happens after activation. If a user goes quiet a month in, that's a retention problem, and the same Schedule-and-state pattern drives it: see the SaaS subscription churn-prevention build for the winback side, and automating customer onboarding in n8n for the broader onboarding picture. The drip is the front door. Keep it idempotent, keep the state in the sheet, and it'll outlast every redeploy.

FAQ

Common questions

How do I build a drip sequence in n8n without HubSpot?
Use a Schedule Trigger to scan a contacts sheet for who's due a step, a Switch to branch by day-since-signup, an email node to send, then write the new step number and timestamp back. The state lives in your sheet or database, not in a paid sequence tool.
How do I stop n8n from sending the same onboarding email twice?
Store the last step sent and a timestamp per contact, and gate every send behind a check that the step hasn't already gone out. Without that re-entrancy guard, an overlapping Schedule run will re-send the same email.
Should onboarding drips use the Wait node or a Schedule Trigger?
For long gaps (days between emails) a Schedule Trigger that re-evaluates state each run survives restarts. The Wait node is fine for short, in-execution pauses but a held execution can be lost on a redeploy.
Stop reading. Start running.

Get the workflow templates this guide is built on

Import-ready n8n JSON, step-by-step setup, and tested end-to-end. One-time payment, own it forever.

Free — $40 value

Get 3 tested n8n templates, free

The full customer package for three real catalog templates — workflow JSON, step-by-step setup guide, credential checklist. Built through the same live-instance release process as everything we sell. Plus new templates and automation guides in your inbox. No spam, unsubscribe anytime.

  • 01Smart To-Do List ManagerPre-built n8n workflow template that automates productivity with OpenAI. Live in about 10 minutes.$14
  • 02Email Follow-Up AutomatorPre-built n8n workflow template that automates crm with OpenAI. Live in about 15 minutes.$12
  • 03Market Trend AnalyzerPre-built n8n workflow template that automates data processing with OpenAI. Live in about 10 minutes.$14