Exploring Apache Flink for Stream Processing
Apache Flink is a distributed stream processing framework designed for high-throughput, low-latency, and stateful data processing.
1. Overview
Flink treats streaming as the primary execution model.
2. Why Flink?
Traditional systems process data in batches.
┌─────────────────────── Flink job (a dataflow DAG) ───────────────────────┐
Kafka ─┤ Source → map/filter → keyBy → window/process (STATE + TIMERS) → Sink ├─► Redis
└───────────────────────────────────────────────────────────────────────────┘
every operator is parallelized into subtasks
This introduces latency because processing only begins after enough data has accumulated.
Flink processes each event as soon as it arrives.
This enables applications that require real-time responses.
Examples:
- Fraud detection
- Ride matching (Grab, Uber)
- Recommendation systems
- Monitoring dashboards
- IoT analytics
- Financial trading
3. Cluster anatomy
A running Flink cluster has three roles:
| Role | What it does |
|---|---|
| Client | Compiles your main() into a dataflow graph and submits it. Not part of the running job. |
| JobManager (JM) | The coordinator. Contains the Dispatcher (accepts submissions, spawns per-job masters + REST/UI), the JobMaster (schedules one job’s tasks, drives checkpoints, reacts to failures), and the ResourceManager (negotiates task slots with the cluster manager). |
| TaskManager (TM) | The worker. A JVM that offers task slots, runs the operator subtasks, holds state, and moves data between tasks over the network stack. |
flowchart TD
C["Client<br/>compiles main() into a job graph"] -->|submit| JM
subgraph JM["JobManager — s-flink-jm"]
direction LR
D["Dispatcher<br/>REST + Web UI :8081"] --> JMR["JobMaster<br/>schedules tasks<br/>drives checkpoints"] --> RM["ResourceManager<br/>negotiates task slots"]
end
subgraph TM["TaskManager — s-flink-tm"]
direction LR
S1["slot 1<br/>source → … → sink"]
S2["slot 2"]
S3["slot 3"]
end
RM -->|assign slots| TM
JMR -. "checkpoint barriers" .-> TM
TM -. "acks / metrics" .-> JMR
4. Core Concepts
DataStream API
The DataStream API is Flink’s programming model for stream processing.
DataStream<Order> orders = env
.fromSource(...)
.filter(...)
.map(...)
.keyBy(...)
.process(...);
Think of it as Java Streams operating continuously on an infinite sequence of events.
Streaming First
Unlike Spark Streaming’s original micro-batch model, Flink processes events one by one.
Kafka
A
B
C
D
E
↓
Flink
Process A
Process B
Process C
Process D
There is no need to wait for a batch to fill.
Benefits:
- Lower latency
- Continuous processing
- Faster response
Stateful Processing
One of Flink’s biggest strengths is state management.
Example:
User clicks
You want to count clicks per user.
Without state:
User A clicked
Flink immediately forgets.
With state:
User A
Count = 15
Every new event updates the stored state.
Event
User A
↓
Current Count = 15
↓
Current Count = 16
Types of State
Value State
Store one value per key.
Example:
User A
Last Login Time
List State
Store a list.
Example:
User
Recent Purchases
Map State
Store a map.
Example:
Product
Region -> Sales
Reducing State
Maintain aggregated values.
Example:
Running Sum
instead of storing every event.
Keyed Streams
State is usually partitioned by key.
Orders
User A
User B
User A
User C
↓
keyBy(User)
Partition A
Partition B
Partition C
Each partition has its own independent state.
| Backend | Working state | Best for |
|---|---|---|
| HashMapStateBackend | On the JVM heap (objects) | Small/medium state, lowest latency, GC-bound |
| EmbeddedRocksDBStateBackend | Off-heap, on local disk (RocksDB), serialized | Very large state (10s of GB–TB), incremental checkpoints |
| ForStStateBackend (new in 2.0) | Disaggregated — state on remote/cloud storage | Cloud-native, elastic, decouples compute from state |
5. Event Time Processing
One of Flink’s defining features.
There are multiple notions of time.
Processing Time
Uses the machine’s current clock.
Event arrives
↓
Current Time = 10:30
Simple but inaccurate if events arrive late.
Event Time
Uses the timestamp carried by the event.
{
"event_time": "10:05:15"
}
Even if it arrives at:
10:30
Flink still processes it as:
10:05
This is critical for distributed systems where network delays are common.
6. Watermarks
How does Flink know when a time window is complete?
It uses watermarks.
Imagine events:
10:01
10:02
10:05
10:03
The last event arrived late.
Flink delays closing windows until the watermark indicates that earlier events are unlikely to arrive.
Events
↓
Watermark
↓
Window closes
Watermarks enable correct handling of out-of-order events.
7. Windowing
Streams are infinite.
Windows divide them into finite chunks.
Tumbling Window
Non-overlapping windows.
0-5
5-10
10-15
Sliding Window
Windows overlap.
0-10
5-15
10-20
Useful for moving averages.
Session Window
Groups events separated by inactivity.
User
Click
Click
Click
(30 min gap)
Click
Produces:
Session 1
Session 2
8. Checkpointing
State is periodically saved.
State
↓
Checkpoint
↓
Storage
If a machine crashes:
Checkpoint
↓
Restore
↓
Continue Processing
Applications continue from the last successful checkpoint instead of starting over.
Exactly-Once Processing
One of Flink’s most valuable guarantees.
Suppose:
Read Event
↓
Update Database
↓
Crash
Without fault tolerance:
Duplicate updates
or
Lost updates
Flink coordinates:
- State snapshots
- Source offsets
- Sink commits
to ensure each event affects the system exactly once (when supported by the source and sink).
9. Savepoints
A savepoint is a manually triggered snapshot.
Used for:
- Upgrading jobs
- Migrating clusters
- Rolling back deployments
Running Job
↓
Savepoint
↓
Deploy New Version
↓
Restore Savepoint
Backpressure
When downstream operators are slower than upstream producers.
Kafka
1000 msg/s
↓
Flink
↓
Database
100 msg/s
The database becomes the bottleneck.
Flink propagates backpressure upstream to prevent memory overload.
10. Parallelism
Operators run in parallel.
Kafka
↓
Map
Map
Map
↓
Sink
Each operator can have its own level of parallelism.
11. Connectors
Flink supports many data sources and sinks.
Sources:
- Kafka
- Pulsar
- Kinesis
- Files
- S3
- JDBC
- RabbitMQ
Sinks:
- Kafka
- Elasticsearch
- Iceberg
- JDBC
- Cassandra
- HBase
- Redis
- S3
CEP (Complex Event Processing)
Detect patterns across multiple events.
Example:
Login Failure
↓
Login Failure
↓
Login Failure
↓
Success
Generate:
Potential Brute Force Attack
instead of analyzing each event individually.
12. SQL Support
Flink supports SQL over streams.
SELECT
user_id,
COUNT(*)
FROM orders
GROUP BY user_id;
The query continuously updates as new events arrive.
Batch Processing
Flink also supports bounded datasets.
Internally:
Batch
↓
Bounded Stream
This allows one engine for both streaming and batch workloads.
13. Flink vs Spark Streaming
| Feature | Flink | Spark Streaming |
|---|---|---|
| Processing Model | Native Streaming | Originally Micro-batch (Structured Streaming improves this) |
| Latency | Very Low | Low |
| Stateful Processing | Excellent | Good |
| Event Time | Native | Supported |
| Watermarks | Native | Supported |
| Exactly Once | Yes | Yes |
| CEP | Built-in | External libraries |
| Streaming First | Yes | No (historically batch-first) |
14. Typical Architecture
Kafka
│
▼
Apache Flink
┌──────────┴──────────┐
▼ ▼
Stateful Processing Windowing
│ │
└──────────┬──────────┘
▼
Aggregation
│
▼
Elasticsearch
│
▼
Grafana
15. When Should You Use Flink?
Flink is a good choice when you need:
- Real-time stream processing
- Stateful applications
- Low-latency processing
- Event-time semantics
- Exactly-once guarantees
- Complex event processing
- Large-scale distributed pipelines
Common use cases include:
- Fraud detection
- Recommendation engines
- Clickstream analytics
- IoT telemetry
- Financial transactions
- Real-time dashboards
- Log analytics
16. Key Takeaways
- Streaming-first architecture: Processes events continuously instead of waiting for batches.
- Stateful processing: Maintains application state across millions of events.
- Event-time semantics: Produces correct results even when events arrive out of order.
- Watermarks: Determine when event-time windows can safely be closed.
- Checkpointing: Periodically snapshots state for fault recovery.
- Exactly-once processing: Prevents duplicate or lost processing when integrated with compatible sources and sinks.
- Windowing: Supports tumbling, sliding, and session windows for stream aggregation.
- Scalability: Distributes work across many machines while preserving state consistency.
- Rich ecosystem: Connects to Kafka, Iceberg, Elasticsearch, databases, cloud storage, and many other systems.