When a new customer signs up, several systems need to be set up at once: an account in the identity system, a customer record in billing, a contact in the CRM, and a welcome email sequence in the marketing tool.
If just one of these steps fails halfway through, you end up with a broken customer: a user who can log in but has no billing account, or a contact in the CRM that nobody can charge. Cleaning that up by hand is slow, error prone and embarrassing when the customer notices.
dataflows runs the whole onboarding as one durable workflow. Every step is recorded. If a step fails, it retries. If it cannot succeed, the workflow rolls back the previous steps so you never end up with a half-created customer.
The workflow can also wait for slow events without using server resources: an email confirmation, a manual review by sales, or the first payment. When the event arrives, the workflow picks up exactly where it stopped.
// Customer onboarding workflow
export const onboarding = defineWorkflow({
id: 'customer-onboarding',
trigger: { type: 'webhook', path: '/signup' },
async run({ event, step }) {
const { email, name } = event.body
const account = await step.run('create-account', () =>
identity.createUser({ email })
)
const customer = await step.run('create-billing', () =>
billing.createCustomer({ email, accountId: account.id })
)
await step.run('create-crm-contact', () =>
crm.contacts.create({ name, email, customerId: customer.id })
)
await step.run('send-welcome', () =>
email.send({
to: email,
template: 'welcome',
data: { name }
})
)
return { accountId: account.id, customerId: customer.id }
},
onFailure: ({ step, context }) => step.run('rollback', () =>
cleanup.undo(context)
)
})