Una banca deve approvare o rifiutare una transazione in 200 millisecondi. Una piattaforma logistica deve reindirizzare 10.000 spedizioni quando un porto chiude. Un sistema manifatturiero deve regolare i parametri di produzione prima che un difetto si propaghi lungo la linea.
Non sono job batch. Sono decisioni in tempo reale che devono essere veloci, corrette e auditabili. E devono funzionare su scala — non decine di decisioni al minuto, ma migliaia al secondo.
Costruiamo questi sistemi. Ecco come funzionano.
Perché il Real-Time È Difficile
Prendere una singola decisione veloce è facile. Prendere migliaia di decisioni veloci al secondo, ognuna corretta e tracciabile, con degradazione graduale sotto carico — è un problema completamente diverso.
Le sfide si accumulano:
Consistenza sotto concorrenza. Quando due decisioni hanno bisogno degli stessi dati e quei dati stanno cambiando, serve un modello di consistenza che sia sia corretto che veloce. La consistenza forte uccide la latenza. La consistenza eventuale introduce errori. Bisogna essere precisi su quali dati devono essere consistenti e quali possono tollerare staleness.
Budget di latenza. In un budget end-to-end di 200ms, ogni componente riceve una fetta. Rete: 20ms. Recupero dati: 40ms. Inferenza del modello: 60ms. Regole di business: 30ms. Serializzazione risposta: 10ms. Restano 40ms per tutto quello che avete dimenticato. Se un componente supera il suo budget, la decisione manca la deadline.
Isolamento dei fallimenti. Quando un servizio downstream fallisce, non può cascadare nella pipeline decisionale. Un modello di fraud detection lento non può bloccare un pagamento. Un servizio di arricchimento che fallisce non può impedire una decisione di routing. Ogni componente necessita di gestione del fallimento indipendente.
Auditabilità a volume. Ai regolatori non importa che prendiate 50.000 decisioni al secondo. Si interessano di una decisione specifica presa alle 14:23:07 del 15 marzo. Il vostro sistema deve produrre una traccia decisionale completa per qualsiasi singola decisione senza impattare il throughput.
L'Architettura
I nostri sistemi decisionali in tempo reale seguono un pattern consistente, raffinato attraverso molteplici deployment:
Pipeline Decisionale
Stream Eventi → Arricchimento → Motore Decisionale → Dispatcher Azioni → Log Audit
↓ ↓ ↓
Feature Store Cache Modello Trace Store
Ogni decisione fluisce attraverso cinque stadi:
Ingestione eventi — Gli eventi arrivano via message queue. Ogni evento è immutabile e timestampato. L'ordine è preservato all'interno delle partition key.
Arricchimento — L'evento grezzo viene arricchito con dati contestuali dal feature store. Storico cliente, attributi prodotto, punteggi di rischio. Questi dati sono pre-computati e in cache — l'arricchimento è un lookup, non un calcolo.
Motore decisionale — L'evento arricchito raggiunge il motore decisionale, che applica una combinazione di regole deterministiche e inferenza del modello. Le regole gestiscono i casi comuni. I modelli gestiscono quelli complessi. La suddivisione è configurabile per tipo di decisione.
Dispatch azioni — La decisione innesca azioni downstream. Approva la transazione. Reindirizza la spedizione. Regola il parametro. Le azioni sono dispatchate in modo asincrono — la decisione è loggata prima che l'azione si completi.
Logging audit — Ogni decisione produce una traccia: input, dati di arricchimento, regole valutate, punteggi del modello, decisione finale e livello di confidenza. Le tracce sono scritte in uno store append-only per compliance e debugging.
Il Feature Store
Il feature store è il componente più sottovalutato. È ciò che rende l'arricchimento abbastanza veloce da rientrare nel budget di latenza.
Le feature sono pre-computate su due scale temporali:
- Feature batch — Aggiornate ogni ora o ogni giorno. Valore lifetime del cliente, pattern storici, statistiche aggregate. Computate da pipeline batch e materializzate nello store.
- Feature streaming — Aggiornate in tempo reale. Velocità transazioni, comportamento recente, dati della sessione corrente. Computate da stream processor e scritte nello store con latenza sotto il secondo.
Al momento della decisione, lo stadio di arricchimento legge dallo store. Nessun calcolo. Solo un lookup chiave-valore. È così che manteniamo l'arricchimento sotto i 40ms anche quando il set di feature include centinaia di attributi.
Model Serving
L'inferenza del modello è il componente più variabile nella pipeline. Un modello che in media impiega 30ms può avere spike a 200ms sotto carico. Gestiamo questo con tre strategie:
Distillazione del modello. I modelli in produzione sono versioni distillate dei nostri modelli di training. Più piccoli, più veloci, ottimizzati per l'inferenza. La perdita di accuratezza è tipicamente sotto lo 0,5% — un compromesso che accettiamo ogni volta per un miglioramento di latenza di 3x.
Timeout con fallback. Se l'inferenza del modello supera il suo budget di latenza, la decisione ricade in modalità solo-regole. La decisione viene comunque presa. È leggermente meno ottimale, ma è puntuale. Tracciamo i tassi di fallback come metrica chiave — un tasso di fallback in crescita significa che il modello necessita di ottimizzazione.
Scaling orizzontale con routing. Le repliche del modello sono load-balanced con routing latency-aware. Le richieste vanno alla replica con la latenza corrente più bassa, non round-robin. Questo attenua la varianza di performance delle singole repliche.
Modello di Consistenza
La decisione architetturale più difficile è il modello di consistenza. Ecco il nostro approccio:
Gli input decisionali sono eventually consistent. I dati del feature store possono essere vecchi di millisecondi. Per la maggior parte delle decisioni, è accettabile. Il punteggio di rischio di un cliente computato 500ms fa è abbastanza vicino.
Gli output decisionali sono strongly consistent. Una volta presa una decisione, è immediatamente visibile a tutti i sistemi downstream. Nessun ritardo, nessun conflitto, nessun "il sistema l'ha approvata ma la dashboard mostra in attesa."
Le tracce decisionali sono immutabili. Scritte una volta, mai modificate. Questo semplifica enormemente la storia audit. Non serve tracciare le modifiche ai record decisionali perché i record decisionali non cambiano.
Questo modello di consistenza misto ci dà le performance dei sistemi eventually consistent dove conta (dati di input) e la correttezza dei sistemi strongly consistent dove conta (output e audit).
Pattern di Scaling
I sistemi decisionali in tempo reale devono gestire picchi di carico senza degradare. Il nostro approccio allo scaling:
Partizionare per tipo di decisione. Tipi di decisione diversi hanno requisiti di latenza diversi e profili di risorse diversi. L'approvazione transazioni ha un budget di 200ms e necessita GPU per l'inferenza del modello. Il routing spedizioni ha un budget di 2 secondi ed è CPU-bound. Girano su infrastruttura separata con policy di scaling separate.
Pre-warm, non auto-scale. L'auto-scaling è troppo lento per sistemi in tempo reale. Quando una nuova istanza è pronta, il picco potrebbe essere finito. Pre-riscaldiamo la capacità basandoci su modelli predittivi di carico. Il volume transazioni del lunedì mattina è prevedibile. Il Black Friday è prevedibile. Pre-warm per il picco atteso, auto-scale per l'inatteso.
Scaricare carico gradualmente. Quando la capacità è veramente esaurita, passate in modalità solo-regole a livello di sistema. L'inferenza del modello è il componente costoso. La modalità solo-regole gestisce 10x il throughput con qualità decisionale leggermente inferiore. È il compromesso giusto quando l'alternativa è droppare richieste.
Cosa Misuriamo
Quattro metriche definiscono la salute di un sistema decisionale in tempo reale:
- Latenza P99 — Non la media, non la mediana. Il 99° percentile. Se l'1% delle decisioni manca la deadline, sono 500 decisioni mancate al secondo a 50K di throughput.
- Accuratezza decisionale — Misurata contro valutazione offline. Come si confrontano le decisioni in tempo reale con decisioni prese con informazione perfetta e tempo illimitato?
- Tasso di fallback — Quale percentuale di decisioni bypassa l'inferenza del modello? Tassi di fallback in crescita indicano problemi infrastrutturali.
- Completezza delle tracce — Quale percentuale di decisioni ha tracce audit complete? Deve essere 100%. Qualsiasi cosa meno è un rischio di compliance.
Quando Ne Avete Bisogno
Non ogni decisione deve essere in tempo reale. Il batch processing è più semplice, più economico e perfettamente adeguato per molti casi d'uso. Costruite un sistema decisionale in tempo reale quando:
- Le decisioni hanno pressione di deadline (transazioni, routing, sicurezza)
- La qualità della decisione degrada con la latenza (la risposta migliore in 5 minuti è peggiore di una buona risposta in 200ms)
- Il volume decisionale rende impossibile la revisione umana
- I requisiti regolamentari richiedono tracciabilità delle singole decisioni
Se il vostro caso d'uso soddisfa questi criteri, l'architettura descritta qui funzionerà. L'abbiamo provata in produzione in diversi settori.
Se non siete sicuri, parliamone. L'architettura sbagliata per il problema sbagliato è più costosa di entrambi i problemi singolarmente.