Go to main content
Kafka Introduction - official lesson image on GinnyTech, created by AD

Introduction to streaming with Kafka

Apache Kafka fundamentals: architecture, key concepts, and usage patterns for analytics.

AD
Created byAndrii Dyshkantiuk
Lesson 111 / 236Level: AdvancedDuration: 22 min

What you will learn

  • Understand the analytical problem and the decision-making context
  • Apply examples, metrics, and controls to real cases

Links

Direct entry into the module.

import pandas as pd

Introduction to streaming with Kafka

Un sistema digitale non aspetta la chiusura del giorno per reagire. Ordini, click, pagamenti e log arrivano mentre il business sta già prendendo decisioni, e la domanda diventa come trasportarli da una parte all’altra senza costruire un’integrazione fragile per ogni coppia di sistemi. Kafka propone una risposta precisa: trattare gli eventi come un log condiviso, ordinato per chiave e riutilizzabile, invece di replicare connessioni punto a punto che si rompono appena cambia qualcosa. Questa lezione parte da quel cambio di modello e mostra perché conta.

Perché lo streaming cambia il problema

Quando i dati si muovono in batch notturni, l’azienda lavora sempre con una fotografia vecchia di ore. Lo streaming non serve solo a fare le stesse cose più in fretta: cambia quali decisioni diventano possibili. Un sistema antifrode che vede la transazione mentre avviene può bloccarla; lo stesso sistema che la vede il giorno dopo può solo scrivere un report.

Conviene leggere Kafka tenendo distinti tre piani. C’è l’evento, cioè il fatto che è accaduto qualcosa. C’è l’infrastruttura che lo trasporta e lo conserva. E c’è la decisione che quei dati dovrebbero migliorare. Kafka è utile quando riduce l’accoppiamento tra sistemi, rende i dati riusabili e conserva abbastanza storia da poter correggere un errore a posteriori. Diventa costoso quando viene scelto solo perché “real time” suona meglio di “batch”, senza che nessuno abbia bisogno della latenza che promette.

Fundamental Concepts

A topic è un flusso logico di messaggi, paragonabile a una tabella in un database: user-events, orders, page-views. Un’azienda può averne centinaia.

Ogni topic è diviso in partizioni per scalare orizzontalmente. Ogni partizione è un log immutabile e ordinato. I messaggi nella stessa partizione mantengono l’ordine, ma l’ordine globale tra partizioni diverse non è garantito: è una delle prime cose che chi arriva da un database sottovaluta.

Theoffset è la posizione di un messaggio dentro la partizione, un numero intero crescente. I consumer tengono traccia dell’offset per sapere fin dove hanno già letto. Il producer scrive su Kafka e decide in quale partizione finisce ogni messaggio, di default tramite l’hash della chiave. Il consumer legge da Kafka e appartiene a un consumer group: ogni partizione viene assegnata a un solo consumer del gruppo, e questo garantisce che ogni messaggio sia processato una volta per gruppo. Il broker è un singolo server Kafka, e un cluster ne tiene più di uno per tolleranza ai guasti e throughput.

Il log immutabile

Qui sta la differenza vera rispetto a una coda di messaggi tradizionale come RabbitMQ, dove un messaggio sparisce appena viene consumato. Kafka invece conserva i messaggi per un periodo configurabile, di default sette giorni ma potenzialmente all’infinito. Questo trasforma Kafka da semplice sistema di messaggistica in un event store vero e proprio.

Le conseguenze pratiche sono concrete. Puoi rileggere i messaggi dall’inizio e riprocessare lo storico quando scopri un bug nella logica a valle. Più consumer group possono leggere gli stessi dati in modo indipendente, senza interferire tra loro. E un nuovo consumer che si aggiunge in seguito può ripartire da zero e recuperare tutta la storia. È il pattern dell’event sourcing: il log di Kafka è la fonte di verità, e ogni sistema a valle deriva il proprio stato leggendolo.

Quando Kafka serve e quando no

Kafka ha senso per flussi di eventi ad alto throughput, indicativamente sopra i 10.000 messaggi al secondo, per microservizi che vuoi tenere disaccoppiati, per event sourcing, change data capture e analytics in tempo reale. Sotto questa soglia il rapporto tra valore e complessità operativa cambia segno.

Kafka non serve, invece, per code di task semplici, dove RabbitMQ o SQS bastano e costano meno; per volumi bassi, sotto il centinaio di messaggi al secondo, dove l’overhead di gestione non si ripaga; e per applicazioni che richiedono transazioni ACID, dove un database resta la scelta giusta. Scegliere Kafka per inerzia, perché lo usano tutti, è uno dei modi più comuni di pagare disciplina operativa senza riceverne i benefici.

Come impostare la scelta

La domanda da fare prima di introdurre uno streaming backbone non è “quale metrica calcolo” ma “quale decisione dovrà migliorare grazie a questo”. Un’integrazione, una dashboard o un consumer group hanno valore solo se riducono l’incertezza di una scelta concreta. Se non cambiano nessuna decisione, sono documentazione o teatro tecnico.

Un modo ordinato di lavorare segue questa sequenza:

  1. definire il problema in linguaggio di business;
  2. identificare l’unità di analisi corretta, che sia utente, account, evento, sessione, ordine o campagna;
  3. check if the data truly measures the phenomenon or just its shadow;
  4. build an interpretable metric;
  5. segmentare, perché una media globale può nascondere due gruppi che si muovono in direzioni opposte;
  6. turn the result into a verifiable recommendation.

Conviene anche dichiarare in modo esplicito l’unità di lavoro (topic, evento, schema, producer, consumer o stream processor), il segnale principale che osservi (latenza, throughput, lag, compatibilità schema, perdita dati), la baseline rispetto a cui leggi il risultato e la decisione attesa, che sia un contratto evento, una pipeline o una policy operativa. Il rischio costante è scambiare un numero disponibile per una prova sufficiente.

Un caso di scelta

Un team deve decidere se sostituire export schedulati e webhook fragili con un backbone a eventi. Prima di portare dentro Kafka conviene valutare il volume reale, il fan out verso i consumer, la necessità di replay, l’ordine per chiave e le competenze operative disponibili. Uno streaming system risolve integrazioni complesse, ma in cambio chiede disciplina nuova: chi possiede i topic, come si gestiscono gli schemi, come si misura il lag.

La logica con cui si legge un risultato resta la stessa anche fuori da Kafka. Se un numero migliora, potrebbe essere un effetto reale oppure una normale oscillazione, e la mossa prudente è cercare un confronto e un segmento. Se un solo segmento si muove più degli altri, la media aggregata sta nascondendo una differenza, quindi conviene separare le coorti. Se il costo cresce insieme al risultato, l’impatto va letto sul margine e non in valore assoluto.

Esempio SQL: una vista di controllo

Il pattern seguente è volutamente generico ma eseguibile sulla maggior parte dei warehouse moderni. Serve a costruire una base analitica con metrica, segmento e finestra temporale, così da confrontare periodi e gruppi senza riscrivere ogni volta la logica.

WITH base_events AS (
  SELECT
    user_id,
    account_id,
    event_type,
    event_time,
    DATE_TRUNC('week', event_time) AS week,
    source,
    device_type
  FROM events
  WHERE event_time >= CURRENT_DATE - INTERVAL '180 days'
    AND user_id IS NOT NULL
),
weekly_user_metrics AS (
  SELECT
    week,
    user_id,
    COALESCE(source, 'unknown') AS source,
    COALESCE(device_type, 'unknown') AS device_type,
    COUNT(*) AS total_events,
    COUNT(DISTINCT DATE(event_time)) AS active_days,
    COUNT(DISTINCT event_type) AS event_diversity,
    MAX(CASE WHEN event_type IN ('purchase', 'subscribe', 'activation') THEN 1 ELSE 0 END) AS reached_key_outcome
  FROM base_events
  GROUP BY week, user_id, source, device_type
)
SELECT
  week,
  source,
  device_type,
  COUNT(DISTINCT user_id) AS users,
  ROUND(AVG(active_days), 2) AS avg_active_days,
  ROUND(AVG(event_diversity), 2) AS avg_event_diversity,
  ROUND(AVG(reached_key_outcome) * 100, 2) AS key_outcome_rate
FROM weekly_user_metrics
GROUP BY week, source, device_type
ORDER BY week, source, device_type;

La query non pretende di dare la risposta finale. Crea una superficie di osservazione fatta di trend, segmenti e differenze tra canali, da cui un analista può formulare ipotesi più precise.

Esempio Python: stabilità e anomalie

Una metrica utile deve essere abbastanza stabile da orientare le decisioni e abbastanza sensibile da segnalare cambiamenti reali. In Python si possono controllare le variazioni anomale settimana su settimana.


# df contiene: week, segment, users, key_outcome_rate
# key_outcome_rate espresso in percentuale, es. 12.4

df = df.sort_values(['segment', 'week']).copy()
df['previous_rate'] = df.groupby('segment')['key_outcome_rate'].shift(1)
df['wow_change_pp'] = df['key_outcome_rate'] - df['previous_rate']
df['rolling_mean'] = df.groupby('segment')['key_outcome_rate'].transform(
    lambda s: s.rolling(4, min_periods=2).mean()
)
df['rolling_std'] = df.groupby('segment')['key_outcome_rate'].transform(
    lambda s: s.rolling(4, min_periods=2).std()
)
df['z_score'] = (df['key_outcome_rate'] - df['rolling_mean']) / df['rolling_std']

anomalies = df[df['z_score'].abs() >= 2].sort_values('z_score')
print(anomalies[['week', 'segment', 'key_outcome_rate', 'wow_change_pp', 'z_score']])

Il valore di questo controllo è pratico: evita di reagire a ogni oscillazione casuale e segnala quando una variazione merita davvero un’indagine. Lo stesso meccanismo può alimentare alert, review settimanali e retrospettive di prodotto.

Errori comuni

Il primo errore è lavorare su dati aggregati troppo presto, perché una media globale può coprire due segmenti che vanno in direzioni opposte. Il secondo è non controllare la qualità del dato: eventi duplicati, tracking incompleto, timezone incoerenti e cambi di definizione producono conclusioni false con una facilità sorprendente. Il terzo è confondere correlazione e causalità, perché se gli utenti che usano una feature convertono di più non significa che la feature causi la conversione; potrebbero usarla proprio perché sono già più motivati.

Per ridurre questi rischi conviene tenere, in ogni analisi, almeno tre controlli minimi: una definizione esplicita della metrica, un confronto per segmento e una verifica contro un periodo precedente o un gruppo di controllo.

Lo streaming con Kafka va trattato come uno strumento decisionale, non come un argomento da manuale. Il valore nasce quando colleghi problema, dati, metrica, segmentazione e azione, e quando ricordi che Kafka conviene solo dove la sua latenza e la sua riusabilità servono a qualcosa. Una buona analisi non si chiude con “il numero è salito” o “il numero è sceso”, ma con una frase operativa: quale decisione prendiamo, con quale confidenza, e quale metrica useremo per sapere se avevamo ragione.

References:

  • Kreps, J., Narkhede, N. & Rao, J. (2011). “Kafka: a Distributed Messaging System for Log Processing.” NetDB 2011.
  • Confluent. (2024). “Apache Kafka Documentation.” kafka.apache.org/documentation.