Intelligenza Artificiale 12 min di lettura 25 novembre 2025

Progettare piattaforme di workflow automation: da Temporal a BPMN

Una guida ingegneristica alla progettazione di piattaforme di automazione dei workflow: durable execution engine, Saga Pattern, architetture trigger/action e orchestrazione event-driven con Temporal, Netflix Conductor e BPMN.

AF

Anna Ferrara

AI & ML Engineer

Ogni sistema software sufficientemente complesso contiene workflow: sequenze di passi che devono avvenire in ordine, con gestione degli errori, retry e compensazioni in caso di fallimento. Che si tratti di un processo di onboarding utente, di un flusso di pagamento multi-step o di una pipeline di elaborazione dati, i workflow non triviali sono ovunque. La domanda non è se gestirli, ma come farlo in modo da scalare, tollerare i guasti e rimanere comprensibile a distanza di mesi.

In Nexora abbiamo progettato e deployato piattaforme di workflow automation in settori diversi: dall'e-commerce alla logistica, dai sistemi finanziari alle pipeline AI. Questo articolo raccoglie le lezioni imparate: quando scegliere un durable execution engine come Temporal, quando è più appropriato BPMN con Camunda, come progettare sistemi trigger/action alla Zapier, e come il Saga Pattern risolve le transazioni distribuite.

Il problema fondamentale: stato e guasti

Un workflow naïve è una serie di chiamate di funzione. Il problema emerge quando la funzione al passo 4 fallisce dopo che i passi 1, 2 e 3 hanno già prodotto side effect nel mondo reale — un'email inviata, un pagamento addebitato, un record creato nel database. Ripartire da zero non è sicuro; ignorare il fallimento non è corretto. Questo è il problema fondamentale che le piattaforme di workflow automation risolvono: mantenere lo stato del processo in modo duraturo, orchestrare i retry in modo intelligente e gestire la compensazione quando qualcosa va storto.

Comparazione degli approcci ai Workflow Engine

Temporal / RestateDurable execution engine — codice come workflow, stato persistente automatico, retry integrati
Netflix ConductorOrchestratore JSON/YAML — workflow come definizioni dichiarative, workers disaccoppiati via queue
Camunda / Flowable (BPMN)Standard BPMN 2.0 — modellazione visuale, adatto a processi human-in-the-loop e compliance
Trigger/Action (Zapier-like)Integrazione no-code/low-code — connettori prebuilt, evento scatena una catena di azioni
Saga PatternPattern architetturale — sequenza di transazioni locali con compensazioni esplicite per il rollback

Temporal: il durable execution engine

Temporal è il workflow engine che ha cambiato il modo in cui molti team pensano all'affidabilità dei processi distribuiti. L'idea centrale è radicale nella sua semplicità: il codice del tuo workflow viene serializzato e rieseguito deterministicamente ogni volta che si riprende da un checkpoint. Il developer scrive codice ordinario — funzioni, loop, condizionali — e Temporal garantisce che quel codice venga portato a termine, anche se i worker si riavviano, la rete va giù o passano giorni tra un passo e l'altro.

L'architettura interna di Temporal si basa su un event log immutabile: ogni azione eseguita da un workflow viene registrata come evento. Quando un worker si riavvia, Temporal riproduce il log degli eventi per ricostruire lo stato in memoria, senza rieseguire gli activity — che potrebbero causare effetti collaterali doppi. Questo approccio, chiamato event sourcing del workflow, è la chiave della sua durabilità. Il risultato pratico è che un workflow Temporal può dormire per settimane aspettando un segnale esterno, occupare zero risorse computazionali nel frattempo, e riprendere esattamente da dove si era fermato.

order-fulfillment-workflow.tstypescript
import { proxyActivities, sleep, defineSignal, setHandler } from "@temporalio/workflow";
import type { OrderActivities } from "./activities";

const {
  reserveInventory,
  processPayment,
  createShipment,
  sendConfirmationEmail,
  releaseInventory,
  refundPayment,
} = proxyActivities<OrderActivities>({
  startToCloseTimeout: "30 seconds",
  retry: { maximumAttempts: 3, initialInterval: "1s", backoffCoefficient: 2 },
});

export const cancelSignal = defineSignal<[{ reason: string }]>("cancel");

export async function orderFulfillmentWorkflow(orderId: string): Promise<void> {
  let cancelRequested = false;
  setHandler(cancelSignal, ({ reason }) => {
    console.log(`Cancellation requested for order ${orderId}: ${reason}`);
    cancelRequested = true;
  });

  await reserveInventory(orderId);

  if (cancelRequested) {
    await releaseInventory(orderId);
    return;
  }

  let paymentProcessed = false;
  try {
    await processPayment(orderId);
    paymentProcessed = true;

    await createShipment(orderId);

    // Temporal can sleep for days without consuming resources
    await sleep("24 hours");
    await sendConfirmationEmail(orderId);
  } catch (err) {
    // Saga compensation: undo side effects in reverse order
    if (paymentProcessed) await refundPayment(orderId);
    await releaseInventory(orderId);
    throw err;
  }
}

Il vantaggio nascosto di Temporal non è solo la durabilità: è la testabilità. I workflow Temporal possono essere testati in modo deterministico con mock degli activity, senza infrastruttura esterna. Questo rende il TDD dei processi distribuiti finalmente praticabile.

Netflix Conductor: orchestrazione dichiarativa

Mentre Temporal usa un approccio code-first, Netflix Conductor definisce i workflow in JSON o YAML. Ogni workflow è un grafo di task; ogni task corrisponde a un worker che esegue la logica di business. Il Conductor server gestisce il routing, il retry e lo stato; i worker sono semplici consumatori di code indipendenti dal linguaggio. Questo disaccoppiamento è il punto di forza principale: team diversi possono implementare worker in linguaggi diversi senza condividere nulla tranne il contratto del task. Netflix dichiara di eseguire oltre un miliardo di workflow al mese su questa architettura.

conductor-onboarding-workflow.yamlyaml
name: customer-onboarding
version: 1
tasks:
  - name: validate_kyc
    taskReferenceName: kyc_check
    type: SIMPLE
    inputParameters:
      userId: ${workflow.input.userId}
    retryCount: 2
    retryDelaySeconds: 30

  - name: setup_account
    taskReferenceName: account_setup
    type: SIMPLE
    inputParameters:
      userId: ${workflow.input.userId}
      kycResult: ${kyc_check.output.result}

  - name: parallel_setup
    taskReferenceName: parallel_tasks
    type: FORK_JOIN
    forkTasks:
      - - name: setup_billing
          taskReferenceName: billing_setup
          type: SIMPLE
          inputParameters:
            accountId: ${account_setup.output.accountId}
      - - name: setup_notifications
          taskReferenceName: notification_setup
          type: SIMPLE
          inputParameters:
            userId: ${workflow.input.userId}

  - name: join_tasks
    taskReferenceName: join_parallel_tasks
    type: JOIN
    joinOn:
      - billing_setup
      - notification_setup

  - name: send_welcome
    taskReferenceName: email_task
    type: SIMPLE
    inputParameters:
      userId: ${workflow.input.userId}
      accountId: ${account_setup.output.accountId}

BPMN: quando i processi diventano collaborativi

Business Process Model and Notation (BPMN 2.0) è lo standard ISO per modellare processi di business. A differenza di Temporal e Conductor, BPMN ha una rappresentazione visuale come first-class citizen: il diagramma non è documentazione del codice, è il codice stesso — o almeno la sua specifica eseguibile. Questo lo rende prezioso in contesti in cui i processi devono essere verificabili da stakeholder non tecnici, soggetti a compliance o includono fasi di approvazione umana.

  • Processi human-in-the-loop: approvazioni, escalation e revisioni manuali in cui un task aspetta l'input di una persona reale
  • Conformità normativa: settori come bancario, assicurativo e sanitario richiedono audit trail e processi certificabili
  • Collaborazione cross-team: il diagramma BPMN diventa il linguaggio comune tra business analyst e sviluppatori
  • Long-running processes: pratiche di mutuo, procedure di gara e processi che possono durare settimane o mesi

Architetture Trigger/Action: il modello Zapier

Le piattaforme trigger/action hanno democratizzato l'automazione per gli utenti non tecnici. L'architettura è elegante nella sua semplicità: un evento (trigger) attiva una catena di azioni. Internamente, una piattaforma come Zapier funziona con un sistema di polling o webhook per rilevare i trigger, una coda di lavoro per distribuire l'esecuzione delle azioni e un modello di connettore che astrae l'autenticazione e l'interazione con ogni servizio esterno. Costruire questa architettura internamente — per integrare sistemi aziendali senza richiedere codice custom — è un caso d'uso valido in molte organizzazioni.

trigger-action-engine.tstypescript
interface Trigger {
  id: string;
  appId: string;
  type: "webhook" | "polling";
  config: Record<string, unknown>;
}

interface Action {
  id: string;
  appId: string;
  operationId: string;
  inputMapping: Record<string, string>; // Template expressions mapping trigger output to action input
}

interface Zap {
  id: string;
  trigger: Trigger;
  actions: Action[];
  enabled: boolean;
}

class TriggerActionEngine {
  async executeZap(zapId: string, triggerPayload: unknown): Promise<void> {
    const zap = await this.zapRepository.findById(zapId);
    if (!zap.enabled) return;

    const context: Record<string, unknown> = { trigger: triggerPayload };

    for (const action of zap.actions) {
      const connector = this.connectorRegistry.get(action.appId);
      const resolvedInput = this.templateEngine.resolve(action.inputMapping, context);

      try {
        const result = await connector.execute(action.operationId, resolvedInput);
        // Each action output is available for subsequent actions via context
        context[`action_${action.id}`] = result;
      } catch (error) {
        await this.errorHandler.handle(zapId, action.id, error);
        break; // Stop chain on unrecoverable error
      }
    }
  }
}

Il Saga Pattern per le transazioni distribuite

In un sistema distribuito non esiste una transazione atomica che abbraccia più servizi. Il Saga Pattern è la risposta matura a questo problema: invece di una singola transazione ACID, una saga è una sequenza di transazioni locali, ciascuna delle quali pubblica un evento o messaggio che innesca il passo successivo. Se un passo fallisce, vengono eseguite transazioni di compensazione — azioni che annullano semanticamente i passi precedenti, anche se non li annullano tecnicamente nel senso ACID del termine.

  1. 1Choreography-based saga: ogni servizio pubblica eventi a cui altri servizi reagiscono. Nessun coordinatore centrale, massima autonomia dei servizi, ma difficile da tracciare e debuggare a scala.
  2. 2Orchestration-based saga: un orchestratore centrale — idealmente implementato su Temporal o Conductor — dirige i passi e gestisce le compensazioni. Più complesso architetturalmente, ma molto più osservabile e testabile.

Quando scegliere cosa

La scelta tra questi approcci dipende da tre variabili: la complessità del processo, il profilo degli stakeholder e i requisiti di osservabilità. Temporal è la scelta default per processi tecnici complessi sviluppati da un team di ingegneri: offre il miglior rapporto tra potenza e costo operativo. BPMN con Camunda è la scelta giusta quando i processi devono essere validati da business analyst, includono fasi di approvazione umana o sono soggetti a audit. Conductor brilla nei sistemi poliglotti in cui team diversi implementano worker indipendenti. Le architetture trigger/action sono appropriate per l'integrazione di servizi SaaS, l'automazione low-code o i prodotti rivolti a utenti non tecnici.

Osservabilità come requisito di prima classe

Indipendentemente dall'engine scelto, un workflow in produzione senza osservabilità adeguata è una bomba a orologeria. Ogni piattaforma di workflow automation deve esporre: la lista delle istanze attive con il loro stato corrente, lo storico delle esecuzioni con i log di ogni passo, le metriche di latenza per attività e workflow, e gli alert per istanze bloccate o con retry esauriti. Temporal fornisce una UI chiamata Temporal Web e un namespace di metriche Prometheus. Per entrambi i sistemi, è consigliabile aggiungere un livello di tracciamento distribuito con OpenTelemetry per correlare le trace dei workflow con quelle degli altri servizi.

Conclusioni

Le piattaforme di workflow automation non sono un'astrazione opzionale — sono l'infrastruttura fondamentale per costruire sistemi distribuiti affidabili. La scelta dell'engine sbagliato genera debito tecnico che emerge nei momenti peggiori: durante un incidente in produzione, durante un audit di compliance, o quando un nuovo ingegnere deve capire come funziona un processo critico. Investire tempo nella scelta deliberata dell'approccio giusto, e nella costruzione di un layer di osservabilità adeguato, paga dividendi per anni.

Tag

Workflow AutomationTemporalConductorBPMNEvent-DrivenSaga PatternOrchestration

Prossimo passo

Hai bisogno di implementare questa architettura?

Il nostro team di ingegneria costruisce e scala i sistemi descritti in questo articolo. Dalla discovery alla produzione — con risultati misurabili.