Core Concepts
The building blocks of stateful stream processing.
Streams
Unbounded streams are continuous, real-time data flows (e.g., click events). Bounded streams are finite datasets (e.g., batch files). Flink handles both with the same API.
Stateful Processing
Operators can maintain local state (counters, windows, custom objects) across events. State is fault-tolerant via checkpointing and can be queried externally.
Event Time & Watermarks
Event time: When an event actually occurred (embedded timestamp). Watermarks: Special markers that track progress in event time, allowing Flink to handle late-arriving and out-of-order events.
Checkpointing
Flink periodically snapshots the state of all operators to durable storage. On failure, it restores from the last checkpoint, providing exactly-once processing guarantees.
Windowing
Group events into finite buckets for aggregation: Tumbling (fixed, non-overlapping), Sliding (overlapping), Session (activity-based gaps), Global (custom triggers).
DataStream API
The primary Java/Scala/Python API for building streaming applications. Supports declarative transformations: map, filter, keyBy, window, reduce, process.
Savepoints
User-triggered, portable snapshots of application state. Unlike checkpoints (automatic), savepoints enable planned upgrades, schema migrations, and A/B testing without data loss.
Connectors
Built-in source/sink connectors for Kafka, Kinesis, JDBC, Elasticsearch, S3/HDFS, and more. Custom connectors via the Source/Sink API.
Architecture
The master-worker model that powers Flink's distributed execution.
JobManager
The master process. Receives job submissions, builds the execution graph, coordinates checkpoints, manages recovery on failures, and schedules tasks across TaskManagers.
TaskManagers
The workers. Each has a fixed number of task slots that execute operator subtasks in parallel. They manage local state backends and exchange data via network buffers.
State Backends
HashMapStateBackend: In-memory, fastest for small state. EmbeddedRocksDBStateBackend: Disk-backed, supports state larger than available memory. Checkpoints to S3/HDFS/GCS.
Setup Guide
Start a Flink cluster locally or via Docker.
Option 1: Docker (Recommended)
Option 2: Native Install
Usage Examples
DataStream API, windowing, and Kafka integration.
Best Practices
Checkpoint Tuning
Set checkpoint interval based on recovery time objectives. Use incremental checkpoints with RocksDB for large state. Configure execution.checkpointing.timeout to catch stalls.
State Backend Selection
Use HashMapStateBackend for fast access with small state (<1 GB). Switch to RocksDB when state exceeds memory capacity. RocksDB supports incremental checkpoints.
Parallelism Config
Set parallelism equal to the number of Kafka partitions for source operators. Over-parallelizing wastes slots; under-parallelizing creates bottlenecks. Use setParallelism() per operator.
Handle Late Data
Configure allowedLateness() on windows to process late events. Use side outputs to capture and separately process events that arrive after the watermark.
Use Savepoints for Upgrades
Before deploying a new version, take a savepoint with flink savepoint <jobId>. Restart from the savepoint to ensure zero data loss during upgrades. Assign stable UIDs to operators.
Monitor Backpressure
Use the Flink Web UI to detect backpressure (tasks shown in red). Backpressure indicates a slow downstream operator. Fix by increasing parallelism, optimizing the bottleneck, or adjusting buffer sizes.
Scaling & Production
Parallelism Tuning
Set per-operator parallelism based on throughput needs. Source parallelism = Kafka partitions. CPU-bound operators need more slots. I/O-bound sinks can use fewer. Use setParallelism() per operator, not just globally.
Reactive Scaling
Flink's Reactive Mode automatically adjusts job parallelism when TaskManagers are added or removed. Combine with Kubernetes HPA to scale TaskManager pods based on CPU or custom Kafka lag metrics.
State Backend at Scale
Use RocksDB state backend for jobs with large state (GB+). It spills to disk and supports incremental checkpointing — only changed SST files are uploaded, reducing checkpoint time from minutes to seconds at TB-scale state.
Rescaling State
Flink supports state rescaling when changing parallelism. Key groups are redistributed across new subtasks. Take a savepoint before rescaling, then restart with new parallelism. Keyed state and operator state handle redistribution differently.
Network Buffer Tuning
Flink's network stack uses buffer pools for data exchange. Increase taskmanager.network.memory.fraction (default 0.1) for high-throughput jobs. Too few buffers cause backpressure; too many waste memory. Monitor via the Flink Web UI.
Cluster Sizing
Rule of thumb: 1 CPU core per slot, 2–4 GB RAM per slot. A job with parallelism 32 needs 32 slots across TaskManagers. Allocate extra capacity for checkpoint overhead, GC pauses, and burst traffic (1.5× baseline).
Frequently Asked Questions
Flink vs Spark Streaming — when to use which?→
Does Flink guarantee exactly-once processing?→
TwoPhaseCommitSinkFunction implements this pattern.Can I use Python with Flink?→
pip install apache-flink. PyFlink runs Python UDFs using an optimized cross-process communication layer. It's production-ready for data engineering but Java/Scala still offer the best performance for latency-sensitive workloads.What happened to the DataSet API?→
How does Flink handle out-of-order events?→
allowedLateness() on windows to still process them, and use side outputs to capture events that arrive too late even for the allowed lateness period.