Logística produz toneladas de eventos: pings de localização, mudanças de status, métricas operacionais, transações financeiras. Postgres OLTP guarda o agora; ClickHouse/Timescale (03-13) guarda agregados. Mas quando você precisa de transformações declarativas em pipeline (limpar, deduplicar, joinar com dimensões, alimentar ML, gerar relatórios contábeis), entra a categoria de data engineering com ferramentas próprias: Spark, Flink, dbt, Airflow, Dagster, Beam, Materialize.
Diferença chave: batch vs streaming. Batch processa snapshots periódicos (diário, hourly). Streaming processa eventos contínuos com windows (5 min sliding, sessions, etc). Real-time analytics, fraud detection ao vivo, dashboards user-facing exigem streaming. Reportes financeiros mensais são batch.
Este módulo é data processing por dentro: lambda vs kappa architectures, streaming engines (Flink, Spark Structured Streaming), batch tools (Spark, dbt, Airflow), consistency em streaming (exactly-once, watermarks, late events), e como integrar tudo via lakehouse (Iceberg/Delta/Hudi) sem virar mil-pipelines spaghetti.
2. Teoria Hard
2.1 Lambda vs Kappa
Lambda (Marz): dois caminhos paralelos, batch layer (correto, lento) + speed layer (rápido, aproximado), unidos em serving layer. Complexidade alta (dois codebases).
Kappa (Kreps): só streaming. Re-process via re-read do log. Reprocessing batch-style sobre stream histórico.
Kappa simplifica e tem ganho com Kafka log retention longa. Lambda persiste em algumas orgs.
Categoria que cresceu 2023-2025: você escreve SQL como em Postgres, engine mantém materialized view incrementalmente atualizada conforme dados chegam. Não é micro-batch, é update real-time conforme cada change.
Modelo conceitual:
Conecta sources (Kafka, Postgres CDC via Debezium, Kinesis, 04-03).
Cada source change propaga; view atualiza com latência sub-segundo.
SELECT retorna sempre o estado atual da view (não scan, é cache).
Exemplo em Materialize:
CREATE SOURCE orders FROM KAFKA BROKER 'kafka:9092' TOPIC 'orders'
FORMAT AVRO USING CONFLUENT SCHEMA REGISTRY 'http://sr:8081';
CREATE MATERIALIZED VIEW revenue_per_user AS
SELECT user_id, SUM(amount) AS total
FROM orders
WHERE status = 'paid'
GROUP BY user_id;
-- agora SELECT retorna em ms, sempre fresco
SELECT * FROM revenue_per_user WHERE user_id = 42;
sql
Materialize:
Construído em Rust sobre timely dataflow (Naiad paper, Frank McSherry).
dbt (data build tool): SQL templated com Jinja, dependências entre modelos, tests, documentação.
Use case: data warehouse transformations. SQL → SQL (não move dados; gera tabelas/views no warehouse).
-- models/orders_daily.sql
{{ config(materialized='table') }}
SELECT date_trunc('day', created_at) as d, count(*) as orders
FROM {{ ref('orders') }}
GROUP BY 1
sql
Dependências (ref) montam DAG. dbt run executa. dbt test valida (not_null, unique, custom).
dbt = padrão modern de transformations em warehouse (Snowflake, BigQuery, Redshift, ClickHouse).
2.10 Orchestration: Airflow, Dagster, Prefect
Pipelines têm dependências, schedules, retries, alerts.
Schema-on-read (data lake) vs schema-on-write (warehouse): trade-off flexibility vs guarantees.
Schema breakages em produção custam horas. Discipline schema reviews.
2.14 Data quality
Tests (dbt): not_null, unique, accepted_values.
Expectations (Great Expectations): suite de validações.
Contracts (DataDog data contracts, Soda): producer commits a schema/quality.
Anomaly detection: drift em distribuição.
Data sem qualidade leva a decisões erradas. Dashboards com NaN minam confidence.
2.15 Streaming joins
Stream-stream join: dois streams em window (last 5min de orders × last 5min de payments).
Stream-table join: enriquece stream com lookup (events × user dimension).
Temporal join: junta com state válido at event time (versioned dimension).
Implementation cuida de state (stream join precisa state ambos lados durante window).
2.16 Exactly-once delivery e effective semantics
Um evento processado só uma vez. Impossível em puro distribuído sem cooperação. Soluções: