Migrating from Iterable
Iterable is a serious enterprise lifecycle platform. The reasons teams move are usually:
- Cost. Iterable starts at ~$2,000/mo and scales steeply with MAU. Apex's per-MAU pricing is roughly 50-70% lower at the same volume tiers.
- AWS-native infrastructure. Iterable is multi-tenant SaaS. Apex sends through your own SES under your AWS account; data residency is your AWS region.
- Unified bandit. Iterable's Journey Experiments are good at the journey level. Apex's Thompson sampler runs across web + email + push + journey arms with one set of math.
- Tighter calibrated-impact integration. Iterable's Send-Time Optimization and Predictive Goals are advanced; the explicit holdout-vs-exposed lift dashboard is uniquely Apex's.
If you're using Iterable for the Workflows product, this is the migration path. If you're using Iterable Push or Iterable Embedded — same path; channels are first-class in Apex.
Concept mapping
| Iterable | Apex | Notes |
|---|---|---|
| Project | Workspace (projectKey) | Same shape. Apex workspaces nest under an Org for cross-workspace cohorts. |
| User Profile | End-User (endUserId) | Apex unifies on a stable per-user identity rather than Iterable's email-as-primary-key model. |
| Lists (Static) | Cohort | Org-level cohorts referenced from journey audiences. |
| Segments (Dynamic) | Audience | Predicates over events + attributes + cohort references. |
| Workflow | Adaptive Journey | Same shape. The migration tool maps the workflow tree directly. |
| Workflow Trigger: Event | Trigger step (event mode) | Direct mapping. |
| Workflow Trigger: API | Trigger step + transactional API call | The journey trigger remains; just call /api/events from your backend instead of Iterable's API. |
| Workflow Trigger: List | Audience-entry trigger | Phase 1 supports event triggers in the UI; audience-entry triggers are wired in the runtime, UI lands in Phase 2. |
| Workflow Step: Wait | Wait step (duration mode) | Direct mapping. |
| Workflow Step: Wait Until Event | Wait step (until_event mode) | Step Functions task tokens; survives across deploys. |
| Workflow Step: Yes/No Split | Branch step (conditional, single condition) | Direct mapping. |
| Workflow Step: Multivariate Split | Branch step (conditional, multiple conditions) | Direct mapping. |
| Workflow Step: Experiment | Branch step (experiment mode, Thompson) | This is usually an upgrade. Iterable's experiments require manual ship; Apex's Thompson sampling shifts traffic continuously and retires losing arms automatically. |
| Workflow Step: Send | Send step | Reuses your existing comm template via the comm picker. |
| Workflow Step: Push / SMS / Embedded | Send step (channel = mobile_push / webhook / in_app) | Apex SMS via the Webhook step + Twilio; everything else is native. |
| Workflow Step: Webhook | Webhook step | HMAC + DNS-rebinding-safe URL validation included. |
| Workflow Step: Update User | Webhook → /api/events | Or direct via the SDK — Apex's user updates are events, not workflow steps. |
| Predictive Goals | Journey-level goalEventName | Set per-journey; calibrated-impact dashboard reads from this. |
| Holdout Group (per-workflow) | Global Holdout | Iterable's per-workflow holdouts compose poorly when workflows overlap. Apex's global holdout gives every journey the same control group — a cleaner statistical contract. |
| Send-Time Optimization | Per-step Wait + adaptive branch | STO maps to a wait-step + adaptive branch optimizing on engagement. Manual but explicit. |
What you can leave as-is
- SES / IP pool — Apex sends through your own AWS account. If you're already doing SES under Iterable's hood, this transfers cleanly.
- APNS / FCM credentials — same; mobile push doesn't proxy through Apex.
- Templates — Iterable's Handlebars + custom templates port to Apex's LiquidJS with mostly-mechanical conversion.
- Event tracking — your event payloads to Iterable's
/api/events/trackmove to Apex's/api/events. Same shape.
Migration steps
1. Inventory
Pull from Iterable's API:
- All Workflows (the JSON tree representation)
- All Segments + Lists
- User catalog with attributes
- (Optional) recent event history
2. Provision Apex
Sign up, create the workspace, install the snippet. Verify the SES domain is set up under your AWS account.
3. Translate
The migration tool emits:
- Apex audiences from Iterable dynamic segments
- Cohorts from static lists
- Adaptive Journey drafts from Iterable workflows
- Communications from email/push templates (Handlebars → Liquid where mechanical; flags non-portable helpers)
4. Review + publish
Walk every translated journey. Pay particular attention to:
- Workflow Experiments → Adaptive Branches: decide which experiments should keep manual control (kept as conditional + ship-when-decided) vs upgraded to adaptive (Thompson takes over)
- Per-workflow holdouts: the migration tool flags these and recommends DELETING them in favor of the global holdout. Don't migrate per-workflow holdouts; they bias your lift estimates when workflows overlap.
- Send-Time Optimization: surfaces as a Wait → adaptive Branch pattern. Review the goal event for each.
5. Cut over
- Pause the Iterable workflow (stops new entrants)
- Publish the Apex journey
- Wait 1-2 weeks for in-flight Iterable workflows to drain
- Sunset the Iterable workspace
On per-workflow vs global holdouts
This is the biggest conceptual difference and worth pausing on.
Iterable lets you set a holdout per workflow — say 10% of workflow A's audience receives nothing. The trouble: workflow A's holdout users are still exposed to workflows B, C, and D. They're not really a control. The holdout users have unique exposure profiles you can't easily compare to non-holdout users.
Apex's global holdout is once per workspace, forever, deterministic. Every journey's lift number uses the same control group. The math is simpler, the statistical contract is cleaner, and you can compare lift across journeys directly.
The migration tool will offer to translate Iterable per-workflow holdouts into Apex's global holdout setting. Most teams that move to this model end up preferring it; if you have a specific reason to want per-workflow control, you can fall back to a custom audience predicate that excludes the bucket.
What's NOT in the migration
- Iterable's reporting suite. Apex's calibrated-impact + branch-performance dashboards answer different questions. Most operators find Apex's leaner.
- Iterable's email template editor history. Templates port; revision history doesn't.
- Iterable's predictive goals model. The training data lives in Iterable. Apex's Thompson sampler builds its own posteriors over journey runs.
FAQ
Does Apex have feature parity with Iterable's Embedded messages? Apex's in-app messaging is in beta. The runtime supports in_app channel; the SDK plumbing is shipping in Phase 2.
Can I run Apex alongside Iterable? Sure. Iterable for marketing campaigns, Apex for adaptive journeys. The two systems share the same SES domain reputation.
How long does a typical migration take? Workspaces with 5-10 workflows: a couple of days. Larger setups (50+ workflows): 1-2 weeks because the review step is human-in-the-loop. Pricing parity from day one.
Get migration help
migration@apex.inc — share your Iterable workspace ID + API key and we'll send back a translated Apex workspace + a workflow-by-workflow upgrade memo.