Il Modulo 5 si è chiuso con Netflix che fa girare batch su petabyte. I dati restano fermi su S3, i job li leggono, i job li riscrivono, e la mattina dopo le dashboard sono aggiornate. Il Modulo 6 parte da dove quell’immagine si rompe. I dati non restano fermi. Il job non finisce. La dashboard vuole essere giusta adesso, non domani mattina. Il passaggio dal batch allo streaming è la decisione di data architecture più impattante che la maggior parte dei team prende dopo la scelta del database, e la mossa concettuale che ci sta sotto è abbastanza piccola da stare in una frase: i dati non sono più bounded.
Questa lezione è l’apertura concettuale. Niente Kafka per ora, niente Flink, niente watermark. Solo il riframing e il trade-off, perché il resto del modulo ha più senso quando il riframing è già a posto.
Bounded contro unbounded data
L’inquadramento più pulito viene da Tyler Akidau, Slava Chernyak e Reuven Lax in “Streaming Systems” (O’Reilly, 2018). Loro sostengono che il vocabolario dell’industria è stato confuso per anni perché mescolava due domande ortogonali: che forma hanno i dati, e quale approccio di processing applichi loro.
Bounded data è un dataset fisso con un inizio noto e una fine nota. Le transazioni della scorsa settimana. I log del mese scorso. il CSV da cinque milioni di righe che il tuo finance team ha appena esportato. Puoi nominarne la dimensione, contarne le righe, elencarne i file. I bounded data hanno un approccio di processing naturale (li leggi, li elabori, scrivi un risultato, hai finito) e quell’approccio è il batch.
Unbounded data è un feed che non finisce. Page view. Letture di sensori. Click degli utenti. Strisciate di carta di credito. Eventi su conti bancari. Topic di Kafka. Il dataset ha un inizio (il giorno in cui hai cominciato a registrare) e nessuna fine (continui a registrare). Non puoi nominarne la dimensione in modo definitivo: nel tempo che impieghi a contare, il conteggio è già sbagliato. Gli unbounded data hanno un approccio di processing naturale (elabori i record man mano che arrivano e non ti fermi mai) e quell’approccio è lo streaming.
Il riframing conta perché la confusione storica ha portato i team a pensare che batch e streaming fossero due mondi diversi. Non lo sono. Bounded contro unbounded è una proprietà dei dati. Batch contro streaming è una proprietà del processing. Puoi applicare entrambi gli approcci a entrambi i tipi di dati, e tutte e quattro le combinazioni esistono in produzione.
Batch su bounded data è il default per il lavoro analitico: ETL notturno, report settimanali, preparazione di training data. Streaming su unbounded data è il default per il lavoro real-time: dashboard, alert, fraud detection. Batch su unbounded data è quello che fai quando prendi uno snapshot di uno stream e lo elabori con strumenti batch (ogni pipeline tipo “carica gli eventi di ieri nel warehouse e fai girare SQL” fa questo). Streaming su bounded data è più raro ma esiste: rieseguire un log finito di eventi storici attraverso un engine di streaming, che è come si presenta il backfill nella Kappa architecture.
Una volta che separi le due domande, le decisioni architetturali si fanno più pulite. La forma dei dati è un fatto. L’approccio di processing è una scelta, fatta in base ai requisiti di latency, alla compatibilità con il tooling, e a cosa il tuo team riesce a operare.
Perché lo streaming conta nel 2026
La tecnologia è viable da un decennio; la domanda continua a crescere. Quattro pressioni spingono i team verso lo streaming.
Lower latency. Un batch giornaliero aggiorna la dashboard alle 6 del mattino. Un batch orario la aggiorna sessanta volte al giorno. Una pipeline di streaming la aggiorna ogni pochi secondi. Per i dirigenti, “abbastanza buono” significava domani mattina. Per gli operations team, “abbastanza buono” significava un’ora fa. Per i sistemi di fraud detection, “abbastanza buono” significa adesso, prima che la transazione venga regolata. La soglia di latency accettabile sta scendendo da quindici anni, e lo streaming è quello a cui ti rivolgi quando il batch non riesce più a centrarla.
Decisioni real-time. Alcune decisioni non possono aspettare. Una transazione di carta di credito deve essere approvata o rifiutata in meno di un secondo. Una recommendation deve renderizzarsi insieme alla pagina. Un trading signal deve scattare prima che il prezzo si muova. Questi workload non possono essere espressi come batch sui dati di ieri; richiedono di elaborare l’evento man mano che arriva.
Metriche operative. Conoscere lo stato del tuo sistema è di per sé un problema di streaming. Istogrammi di latency delle API, error rate per endpoint, profondità delle code, saturazione delle connessioni al database. Gli stack moderni di observability (Prometheus, Datadog, OpenTelemetry) sono sistemi di streaming anche quando nessuno nel team li pensa così.
Event-driven architecture. Un sistema a microservizi comunica tramite eventi. L’order service scrive un evento OrderPlaced; l’inventory service lo legge e decrementa lo stock; l’email service manda una conferma; l’analytics service aggiorna la dashboard. Ogni consumer è la sua pipeline di streaming sulla stessa sorgente, e la spina dorsale di integrazione che li lega insieme è un sistema di streaming. Il Modulo 7 copre i pattern event-driven in profondità.
Il costo: lo streaming è più difficile
Il riframing fa sembrare lo streaming un upgrade gratuito. Non lo è. Tre problemi strutturali diventano più difficili quando passi da bounded a unbounded data.
Lo state management è più difficile. Un job batch legge il suo input, calcola, scrive l’output, e termina. Lo state vive in memoria per la durata del job, poi sparisce. Un job di streaming gira per sempre, e qualsiasi aggregazione che calcola (un counter per utente, una windowed average, un running join) deve essere ricordata attraverso restart, attraverso failure di macchine, attraverso ribilanciamenti del cluster. La lezione 43 copre come i principali engine memorizzano questo state; la lezione 45 copre cosa significa “exactly-once” in un sistema il cui state deve sopravvivere ai failure.
Le time semantics sono più difficili. Un job batch partiziona per data perché la data è dentro i dati. Un job di streaming deve gestire due tempi diversi contemporaneamente: il tempo in cui l’evento è successo (event time) e il tempo in cui il sistema lo ha elaborato (processing time). Non sono uguali, perché gli eventi arrivano in ritardo, fuori ordine, o dopo che la rete li ha inghiottiti per quindici secondi. La lezione 44 copre i watermark, il meccanismo che gli engine di streaming usano per ragionare sull’event time senza aspettare in eterno i ritardatari.
Il failure recovery è più difficile. Un job batch che fallisce a metà strada può essere rieseguito dall’inizio. Un job di streaming che fallisce a metà strada ha emesso output per ore; “rieseguire dall’inizio” significa riemettere, il che è sbagliato a meno che il downstream non sia idempotente. La lezione 38 ha coperto i batch idempotenti; la versione streaming è strutturalmente simile ma più implacabile perché la superficie di failure è continua.
La lettura onesta: lo streaming è la risposta giusta quando latency o volume lo giustificano, ed è la risposta sbagliata quando nessuno dei due lo fa. Andare verso lo streaming perché suona moderno è un modo per triplicare la complessità operativa di un workload che andava benissimo come cron job.
La vista a continuum
Lo split tra batch e streaming sembra categoriale quando lo descrivi in slide. In pratica è un continuum, e la posizione sul continuum è impostata dalla dimensione della finestra che elabori.
Un batch giornaliero è un batch con una finestra di un giorno. Il job gira una volta alle 2 di notte, legge l’ultimo giorno di dati, e produce un risultato. Un batch orario è un batch con una finestra di un’ora. Un microbatch ogni minuto è la stessa forma con una finestra da sessanta secondi. Un microbatch ogni secondo è di nuovo la stessa forma, solo più veloce. A un certo punto smetti di chiamarlo batch e cominci a chiamarlo streaming, ma la linea è sfocata. Spark Structured Streaming, che la lezione 43 copre, è esplicitamente un sistema di microbatch: elabora i record in piccoli batch, tipicamente ogni poche centinaia di millisecondi, e presenta una API di streaming sopra un engine batch. Flink, dall’altra parte, elabora i record uno alla volta man mano che arrivano, senza batching, ed è descritto come un engine “true streaming”. La distinzione conta per la latency a scala di millisecondi e per la forma dello state model. Non conta per la domanda concettuale se stai elaborando bounded o unbounded data.
La vista a continuum spiega perché i team possono migrare gradualmente. Un batch notturno diventa un batch orario quando il business chiede dati più freschi. Il batch orario diventa un microbatch da quindici minuti quando un’ora è troppo lenta. Il microbatch diventa una pipeline di streaming quando quindici minuti sono troppo lenti. Ogni passo accorcia la finestra; l’architettura cambia forma gradualmente invece che in un solo salto.
flowchart LR
subgraph Bounded[Bounded data]
B1[Last week of transactions]
B2[Monthly export]
B3[Historical archive]
end
subgraph Unbounded[Unbounded data]
U1[Page views]
U2[Sensor readings]
U3[Kafka topic]
U4[CDC log]
end
Bounded -->|natural fit| Batch[Batch processing]
Unbounded -->|natural fit| Stream[Stream processing]
Bounded -.->|possible| Stream
Unbounded -.->|via snapshot| Batch
Diagramma da creare: una versione curata che mostra due colonne di sorgenti dati (bounded a sinistra, unbounded a destra) con frecce che scendono ai due approcci di processing. Frecce solide per il fit naturale, tratteggiate per le combinazioni incrociate. Il punto è che la forma dei dati e la scelta del processing sono indipendenti, e le combinazioni incrociate esistono entrambe in produzione.
I due stili di architettura
Quando i team costruiscono pipeline di streaming, due architetture ricorrenti emergono in letteratura. Vale la pena nominarle ora perché il resto del Modulo 6 continuerà a riferirsi a loro.
Lambda architecture, nominata da Nathan Marz intorno al 2011 e dominante dal 2014 al 2018, fa girare due pipeline in parallelo: una pipeline batch che produce risultati accurati dall’intero dataset storico, e una pipeline di streaming che produce risultati approssimati con bassa latency. I risultati delle query sono fusi al momento della lettura: la vista batch è corretta ma stale, la vista streaming è fresca ma approssimata, e l’applicazione le combina. Lambda era una risposta pragmatica ai limiti degli engine di streaming nei primi anni 2010, quando “exactly-once” era un argomento di ricerca e “stateful streaming at scale” era doloroso. Il costo era far girare e mantenere due pipeline parallele, con due implementazioni di ogni transformation, due insiemi di bug, due insiemi di problematiche operative.
Kappa architecture, nominata da Jay Kreps nel 2014, fa girare una singola pipeline di streaming. Il batch non è un sistema separato; il batch è una pipeline di streaming che riproduce un lungo segmento bounded dello stesso log. Se hai bisogno di ricalcolare la storia, punti un consumer fresco all’offset zero del topic Kafka e lo lasci girare. L’engine di streaming gestisce sia la coda live sia il backfill storico con lo stesso codice. Kappa è diventata viable man mano che gli engine di streaming (Flink in particolare) hanno sviluppato strong exactly-once semantics, state durabile, e meccanismi di savepoint. Entro il 2020 era l’architettura da cui partivano i nuovi sistemi di streaming, e Lambda era una scelta legacy invece che un default. La lezione 46 copre i trade-off tra le due in dettaglio.
La ragione per introdurle adesso è che la scelta influisce su quale tooling vai a prendere. Lambda ha bisogno sia di un engine batch sia di un engine di streaming, incollati insieme da un serving layer. Kappa ha bisogno di un engine di streaming forte e di un log durabile e replayable. Il Modulo 6 passa la maggior parte del suo tempo sulla forma Kappa perché è quello che la maggior parte dei team del 2026 sta costruendo, ma la discendenza di Lambda è ovunque nel codice legacy.
Cosa copre il Modulo 6
Le prossime sette lezioni percorrono lo stack di streaming moderno. La lezione 42 copre Kafka, il log dominante e il substrato da cui ogni altro componente legge e scrive. La lezione 43 confronta i tre engine di stream processing che contano nel 2026: Flink, Kafka Streams, Spark Structured Streaming. La lezione 44 copre event time, watermark, e le primitive di windowing, la lezione concettualmente più densa del modulo perché le time semantics sono il punto in cui lo streaming smette di sembrare batch veloce. La lezione 45 copre l’exactly-once processing: cosa significa davvero il termine e quali garanzie puoi comprare. La lezione 46 copre Lambda contro Kappa in profondità. La lezione 47 copre il Change Data Capture, il pattern che trasforma il transaction log di un database in un topic Kafka. La lezione 48 chiude il modulo con il case study di streaming di Uber.
Il filo che attraversa tutte è il riframing di questa lezione. I bounded data hanno una forma naturale, gli unbounded data ne hanno un’altra, e le prossime sette lezioni sono il toolkit per il caso unbounded. Il toolkit è reale; il costo è reale; la leva è enorme quando ne hai bisogno.
Citazioni e letture di approfondimento
- Tyler Akidau, Slava Chernyak, Reuven Lax, “Streaming Systems” (O’Reilly, 2018). Il libro di riferimento per il modello concettuale usato in questo modulo. Il riframing bounded/unbounded, la distinzione event-time/processing-time, e il modello di windowing vengono tutti da questo libro e dai precedenti paper di Google che ci stanno dietro.
- Tyler Akidau, “The world beyond batch: Streaming 101” e “Streaming 102”, O’Reilly Radar, 2015 e 2016. I due saggi che hanno introdotto l’inquadramento alla community più ampia prima dell’uscita del libro. Vale ancora la pena leggerli; le mosse concettuali sono le stesse.
- Nathan Marz, “Big Data: Principles and Best Practices of Scalable Real-Time Data Systems” (Manning, 2015). Il libro originale sulla Lambda architecture.
- Jay Kreps, “Questioning the Lambda Architecture”, O’Reilly Radar, 2014,
https://www.oreilly.com/radar/questioning-the-lambda-architecture/(consultato 2026-05-01). Il saggio che ha nominato Kappa e ha argomentato contro il far girare due pipeline. - “Designing Data-Intensive Applications” (Martin Kleppmann, O’Reilly, 2017), capitolo 11. Il riferimento standard per lo stream processing in un contesto di sistemi, con un inquadramento più conservativo rispetto al libro di Akidau.