Skip to content

Onboarding drips · Trial conversions · Churn prevention

User lifecycle workflows that run themselves.

Onboarding drips, trial-to-paid conversions, usage-based billing, churn prevention, and re-engagement sequences — all crash-safe, with timezone-aware scheduling and conditional branching based on what your users actually do.

The problem

SaaS lifecycle logic is always the messiest code.

Every SaaS team builds the same fragile infrastructure: cron jobs for trial expiry, background workers for drip campaigns, and custom state machines for every lifecycle stage. It breaks on every deploy.

Onboarding sequences break on deploys

You rolled out a new feature and restarted. Now 2,000 users are stuck mid-onboarding with no record of which step they were on. Some get duplicate emails. Others get nothing.

Trial expiry logic scattered across the codebase

Trial countdown lives in a cron job, the upgrade nudge is in a Sidekiq worker, the grace period is a background task, and the downgrade is a database trigger. Nobody knows where all the pieces are.

No conditional branching based on user behavior

You want to send different emails depending on whether a user completed setup, invited teammates, or connected an integration. Instead, everyone gets the same generic sequence.

Timezone-unaware scheduling annoys global users

Your 9am activation email lands at 3am in Tokyo. Users in Europe get weekend messages. There is no clean way to schedule per-user timezone delivery without a custom scheduling layer.

No way to pause or cancel sequences when users act

A user upgrades to paid, but the trial expiry sequence keeps running and sends them a downgrade warning anyway. Stopping a running sequence requires manual database surgery.

Custom state machines for every lifecycle stage

Onboarding needs a state machine. Trial management needs another. Churn prevention needs a third. Each one tracks position, handles retries, and manages transitions differently.

Use cases

Every stage of the user lifecycle. One engine.

Orch8 is a general-purpose durable execution engine. These are the SaaS lifecycle workflows teams reach for it most.

Onboarding drip campaigns

Adaptive onboarding that reacts to user behavior

Send a welcome email on signup. Wait 2 days. Check if the user completed setup. If yes, send pro tips and feature highlights. If not, send a nudge with a setup guide. Branch again based on whether they invited teammates. Every step survives deploys.

user activation workflowbehavior branchingdurable

Trial-to-paid conversion

Convert trials with perfectly timed nudges

Start a 14-day sequence on trial creation. Check usage at day 3 and day 7. Send relevant nudges based on which features they explored. Warn at day 12. Convert or downgrade at day 14. Cancel the sequence instantly when they upgrade early.

trial to paid conversionsignalsconditional logic

Usage-based billing

Metered billing that never double-charges

Monitor usage at the end of each billing cycle. Calculate charges based on consumption tiers. Generate an invoice. Process payment with retry on failure. Notify the customer. Every step is memoized — a crash mid-billing never results in duplicate charges.

saas billing workflowmemoizationcrash-safe

Churn prevention

Catch disengaged users before they cancel

Detect 7 days of inactivity. Send a re-engagement email. Wait 3 days. If still inactive, offer an incentive or discount. Escalate high-value accounts to customer success. Auto-cancel only after the full sequence completes with no response.

churn prevention automationescalationre-engagement

Feature adoption sequences

Drive adoption of new features with targeted outreach

When you ship a new feature, trigger a sequence for users who would benefit. Send an announcement. Wait 5 days and check if they tried it. If yes, send advanced tips. If not, send a walkthrough with a video. Follow up once more, then stop.

feature adoptiontargeted notificationuser segments

Customer health scoring

Route accounts by risk level automatically

Collect usage signals, support ticket frequency, NPS scores, and login patterns. Calculate a health score. Route high-risk accounts to customer success with full context. Automate low-touch interventions for medium-risk. Leave healthy accounts alone.

health scoringautomated routingcustomer success

How it works

Three steps to a durable lifecycle workflow

1

Define your onboarding sequence as JSON

Describe the lifecycle workflow as a series of steps, delays, and conditional branches. No SDK required. The engine handles scheduling, timezone delivery, crash recovery, and state tracking.

{
  "id": "user_onboarding",
  "blocks": [
    {
      "type": "step",
      "handler": "send_welcome_email",
      "params": { "template": "welcome_v2" }
    },
    {
      "type": "step",
      "handler": "wait",
      "delay": { "days": 2, "business_days_only": true }
    },
    {
      "type": "step",
      "handler": "check_user_setup"
    },
    {
      "type": "router",
      "routes": [
        {
          "condition": "{{outputs.check_user_setup.completed}}",
          "blocks": [
            {
              "type": "step",
              "handler": "send_pro_tips",
              "params": { "template": "power_user_tips" }
            }
          ]
        },
        {
          "default": true,
          "blocks": [
            {
              "type": "step",
              "handler": "send_setup_nudge",
              "params": { "template": "finish_setup" }
            }
          ]
        }
      ]
    },
    {
      "type": "step",
      "handler": "wait",
      "delay": { "days": 5, "business_days_only": true }
    },
    {
      "type": "step",
      "handler": "check_activation"
    }
  ]
}
2

Implement handlers as plain HTTP endpoints

Each handler is a POST endpoint in any language. Query your database, call your ESP, check user state — Orch8 memoizes the output. If the engine restarts, completed handlers return the cached result.

// TypeScript — check if user completed setup
app.post('/workers/check_user_setup', async (req, res) => {
  const { context } = req.body;
  const userId = context.data.user_id;

  const user = await db.users.findById(userId);

  const completed =
    user.profile_filled &&
    user.workspace_created &&
    user.first_integration_connected;

  // Output is memoized — if engine crashes after this,
  // the result is preserved, never re-queried
  res.json({
    completed,
    missing_steps: [
      !user.profile_filled && 'profile',
      !user.workspace_created && 'workspace',
      !user.first_integration_connected && 'integration',
    ].filter(Boolean),
    days_since_signup: daysSince(user.created_at),
  });
});
3

Start instances from your signup webhook

Trigger a lifecycle sequence from any event — signup webhook, Stripe event, product event. Orch8 schedules and tracks execution from start to finish. Use an idempotency key to prevent duplicate sequences.

POST /sequences/user_onboarding/instances
{
  "context": {
    "data": {
      "user_id": "usr_8a3f2c",
      "email": "jamie@acme.co",
      "name": "Jamie",
      "plan": "trial",
      "timezone": "America/New_York",
      "signed_up_at": "2025-03-15T14:30:00Z"
    }
  },
  "idempotency_key": "onboarding-usr_8a3f2c"
}

Capabilities

Built for SaaS lifecycle complexity

Every feature maps to a real SaaS need. No generic workflow abstractions — these are the primitives you actually use when building onboarding, conversion, and retention workflows.

Business-day scheduling

Set business_days_only on any delay. Emails scheduled for Saturday automatically shift to Monday morning. No weekend notifications, no holiday sends, no annoyed users.

Per-user timezone delivery

Pass a timezone in the instance context. Delays resolve relative to the user's local time. Your 9am activation email arrives at 9am in Tokyo, London, and New York — automatically.

Signals: cancel when users convert

Send a signal to cancel the trial expiry sequence the moment a user upgrades to paid. No more downgrade warnings sent to paying customers. Sequences respond to external events in real time.

A/B split blocks for experiments

Route users through different onboarding paths with split blocks. Send 50% to a video-first flow and 50% to a text-first flow. Measure which path drives higher activation.

Rate limiting per ESP

Set rate limits per email service provider, per domain, or per sending identity. Orch8 tracks usage with a sliding window and defers overages — emails queue, never drop.

Output memoization: no duplicate emails

If the engine crashes after sending an email but before recording the step, the output is already memoized. On restart, the step returns the cached result. Users never receive duplicate messages.

Crash recovery across deploys

Deploy as often as you want. Instances stalled mid-sequence are auto-detected on engine restart and resume from the last completed step. No user is left stuck in a broken onboarding flow.

Resource pools for sender rotation

Rotate across multiple sending domains or IPs with resource pools. Orch8 distributes sends across pool members, tracks warmup limits per domain, and balances load automatically.

Retry with configurable backoff

Each step defines its own retry behavior. If a payment charge fails, retry after 3 days with exponential backoff. If an email send fails, retry after 5 minutes. All retries are durable.

Full audit trail per user

Every step, every delay, every routing decision is persisted in PostgreSQL. Know exactly when each user received each email, which branch they took, and where they are in the sequence right now.

What you don't build

6 problems you never have to solve

Every SaaS team that runs lifecycle workflows eventually builds all of these. With Orch8, none of them are your problem.

Email sequence state machine

No tracking which step a user is on, what's been sent, or where to resume after a deploy. Orch8 owns the sequence position and resumes automatically.

Trial expiry countdown logic

No cron job that checks trial_ends_at every minute. Define the trial sequence as JSON with delays and branches. Orch8 schedules each step and handles the countdown durably.

Timezone-aware scheduler

No date-fns gymnastics for per-user timezone delivery. No DST transition bugs. Pass a timezone in context — delays resolve to the user's local time automatically.

User lifecycle tracker

No custom database table tracking onboarding_step, trial_status, and last_email_sent. The sequence instance is the source of truth. Query it via the API.

ESP rate limiter

No Redis-backed counters for SendGrid or Postmark quotas. Set a rate_limit_key and a limit on the email step. Orch8 tracks usage and defers overages.

Deploy-safe job recovery

No heartbeat polling for stuck jobs. No stuck-sequence detector. Instances stalled mid-execution are auto-reset on engine restart and resume from the last checkpoint.

Your SaaS lifecycle shouldn't depend on cron jobs.

Tell us what you're building. We'll reach out within 24 hours to walk you through a working example — onboarding drip, trial conversion, churn prevention, or custom.

No credit card required. Self-host free with no feature gates.