Adaptive Journeys
Adaptive Journeys are self-optimizing lifecycle workflows. They're a leg of the Apex Loop — the place where everything you know about your users (from audiences and beliefs) gets composed into a sequence of nudges, branches, and decisions that learn over time.
A journey is a directed graph of steps:
- Trigger — the entry condition (an event, a schedule, or audience entry)
- Wait — a duration or "until-event" pause
- Branch — a routing decision; either conditional (rules-based) or adaptive (Thompson-sampled)
- Send — a communication fire over email, in-app, or push
- Webhook — an outbound call to your own systems
- Exit — the journey terminates
Each step has a stable ID and routes to a next step. Branches fan out; everything else is linear.
Why "Adaptive"
Static drip campaigns ship a sequence and hope. Adaptive Journeys ship a sequence AND learn what's working — automatically routing more users through the variants that are converting, while keeping the global holdout untouched as the control.
You don't decide when arm B "wins" over arm A. The journey's Adaptive Branch does, by Thompson-sampling each arm's posterior conversion rate every time a user reaches the step.
How journeys differ from communications
| Communication | Adaptive Journey | |
|---|---|---|
| Shape | A single message | A graph of steps |
| When it fires | Manual or via trigger event | Triggered + walked over time |
| Optimization | Variants within the message (subject lines, copy) | Branches between strategies (which message, which path, when) |
| Storage | TenantCommunication | AdaptiveJourney (versioned) |
A Send step in a journey references an existing communication — you don't re-author copy inside the journey. Edit the comm, and it stays connected. Publish the journey, and the Send step pins the comm version so in-flight users keep using the version that was current at journey publish time.
Versioning
Journeys are versioned the same way communications are. Each publish creates an immutable v<n> record; the latest pointer advances atomically. In-flight executions stay on the version they started; new executions pick up the latest.
This means you can edit a published journey freely — your changes live in the draft until you re-publish. The two-version-history (draft + latest) keeps the editor's mental model simple.
Subjects
Phase 1 ships end-user subjects only. Affiliate-subject journeys (where the journey runs against an affiliate, not an end-user) are reserved for Phase 2 alongside the Partner Network expansion.
The runtime is tested against end-user identity resolution, end-user preferences, and end-user comm channels (email + in-app + mobile push). Schedule and audience-entry triggers run on a 1-minute EventBridge tick — schedule fires when the cron matches, audience-entry fires on the cohort transition (out → in).
What you author vs. what's automatic
You decide:
- The shape of the graph (what steps in what order)
- Which communication each Send step uses
- Which event triggers entry
- The optimization goal for each Adaptive Branch (e.g. "subscription.created within 7 days")
- The audience (which subset of end-users is eligible)
The journey decides automatically:
- Which arm of an Adaptive Branch each user gets (cold-start round-robin → Thompson sampling)
- Whether each Send is allowed (eligibility contract: opt-out, suppression, frequency cap, holdout)
- When to retire a losing arm (it stops being sampled once posteriors stabilize)
- How to attribute outcomes to arms (within the configured attribution window, censoring stopped/failed runs)
Related
- Adaptive Branches — the Thompson-sampling math
- Global Holdout — how incrementality is measured
- Audiences — who can be in a journey
- Communications — what a Send step references