Les workflows client et serveur partagent un seul format JSON et un seul interpréteur, @malla/engine. Seul change l'adaptateur qui exécute chaque étape. Les workflows sont interprétés, jamais compilés : la publication stocke une version immuable et un seul runner sert tous les sites.
Trois adaptateurs
interface StepAdapter {
do<T>(name: string, retry: RetryPolicy | undefined, fn: () => Promise<T>): Promise<T>
sleep(name: string, duration: string): Promise<void>
waitForEvent(name: string, opts: { type: string; timeout?: string }): Promise<unknown>
}
Format des étapes
interface WorkflowStep {
id: string
action: string // core.<name> or <pluginId>.<name>
params?: Record<string, unknown> // values may be Bindings at any depth
branches?: Record<string, WorkflowStep[]> // then/else, body, try/catch, cases, lanes a…h
disabled?: boolean
retry?: { limit: number; delay?: string; backoff?: 'constant' | 'linear' | 'exponential' }
}
Le résultat de chaque étape est stocké dans steps[id]. Le contrôle du flux imbrique des listes d'étapes dans branches. Un workflow serveur est durable si et seulement s'il contient un core.sleep ou un core.waitForEvent activé.
Règles de rejeu
Cloudflare Workflows réexécute le code et renvoie les résultats en cache pour les étapes terminées. Par conséquent :
- Les noms d'étapes sont des chemins déterministes,
<branch>/<loop index>/<step>, pour que les boucles et les branches se rejouent correctement ; les voies parallèles ajoutent<name>/<lane>/<step>. - Tout ce qui se trouve hors d'une étape est déterministe ;
fn.now()s'exécute à l'intérieur des étapes. - La version du workflow est figée dans les paramètres de l'exécution : les exécutions en cours ne voient donc jamais les modifications.
- Les résultats d'étapes conservés dans l'historique sont limités à 16 Ko chacun.
Câblage du runner
apps/runner (Worker)
├─ POST /run/:siteId/:workflowId test and editor runs (api)
├─ ALL /api/* endpoints + webhooks (sites)
├─ Workflows binding → SiteWorkflow durable runs
├─ Durable Objects → SiteScheduler (cron alarms), RunStream (live test runs),
│ SiteDatabase (tables, visitors)
└─ Worker Loader → runJs isolates (no bindings, no secrets)
Les workflows serveur publiés sont stockés dans KV sous wf:<environment>:<siteId>, avec leurs routes HTTP et leurs planifications cron. Une publication replanifie les crons du site.
Limites
| Client | Serveur | |
|---|---|---|
| Étapes par exécution | 200 | 1 000, moins selon le forfait |
| Profondeur d'imbrication | 8 | 8 |
| Itérations de boucle | 1 000 | 1 000 |
| Nouvelles tentatives par étape | — | 5 |
| Délai d'expiration d'une exécution synchrone | — | 30 s |
| Voies parallèles / cas de switch | 8 / 32 | 8 / 32 |