
A pragmatic transition from a homegrown external metrics scaler to a customized OSS Flink Autoscaler powered by Temporal
This article shares Netflix's engineering journey of moving from their custom-built external autoscaling tool to the community-driven Apache Flink Autoscaler. To adapt the OSS logic to Netflix-scale workloads, they built a robust orchestration service powered by Temporal and resolved critical metric and engine-level bottlenecks. The post provides deep insights into metric reliability, sensible defaults, and future optimizations using disaggregated state.
Highly recommended for platform engineers, data architects, and site reliability engineers looking to scale large, stateful stream processing clusters efficiently while keeping infrastructure costs low.
Netflix managed over 30,000 Flink jobs and faced massive inefficiencies in manually scaling resources for complex stateful DAGs. Their homegrown external autoscaler relied on coarse, container-level metrics from Atlas, which failed to perceive inner-job bottlenecks in multi-operator pipelines and could easily lead to performance degradation invisible to CPU metrics.
Netflix adopted the community's 'Apache Flink Autoscaler' library to analyze True Processing Rate (TPR) from within the job DAG. They integrated this standalone core with a Spring Boot application orchestrated by Temporal workflows, while contributing and implementing custom optimizations to Flink's runtime, such as metric caching, preserving forward chaining, and async sink backpressure detection.
Deploying the OSS-based autoscaler allowed the client telemetry and logging team to reduce annualized Flink compute expenditures by 58%, saving approximately $1.1 million annually. The isolated, per-job workflow model eliminated failure propagation, and the scaling platform successfully supported extremely large jobs with up to 3,000 Flink subtasks.
Trade-off
To avoid aggressive downscaling that leads to CPU saturation, lag spikes, and disruptive scaling loops, Netflix compromised on absolute resource utilization by lowering the target utilization parameter to 0.45 (compared to the community default of 0.7). Additionally, the most significant scaling bottleneck remains the restart and state recovery time of Flink itself rather than the scaler's decision speed.
The theoretical maximum throughput that an operator subtask can process if it were 100% busy without any backpressure or idle time. It is computed by dividing observed throughput by the active busy fraction.
A developer-focused stateful orchestrator that manages complex, distributed, and long-running workflows with built-in persistence, retry policies, and fault isolation.
A decoupled state-backend architecture in Flink 2.0 that offloads state storage to remote distributed storage instead of keeping it bound to local task manager disks.




