SevenTnewSAI & tech news, explained

Stream processing · FLIP-21

Apache Flink wants to stop copying data at every operator. That's the easy part

FLIP-21 would let Apache Flink stop copying data between every chained operator, replacing a long-standing safety default with three selectable modes. DEFAULT, COPY_PER_OPERATOR, and FULL_REUSE split the difference between speed and caution. The migration question is still open.

Emmanuel Fabrice Omgbwa Yasse AI-assisted

2026-09-14 · 4 min read

Apache Flink wants to stop copying data at every operator. That's the easy part

Apache Flink's streaming runtime copies data every time it moves between two chained operators. That behavior was built in deliberately, to head off trouble with mutable objects when state backends store objects on the heap. The copy guarantees that what an operator passes onward will not change underneath anyone else still holding a reference.

FLIP-21, a change proposal now under discussion, aims to remove most of that cost without giving up the guarantee. Its writeup lists four problems with the current approach. Copying is expensive for complex types such as Avro, Thrift, and JSON. Keyed operations that run after a shuffle never needed the copy, because they sit first in the chain. The DataSet API does not copy at each step, so the two halves of Flink follow different rules for the same data. And the option that controls the whole behavior, enableObjectReuse(), is misnamed, since it does not actually reuse objects.

The writeup describes those costs in qualitative terms and attaches no benchmark figure to any of them, so the proposal does not establish how much a typical pipeline loses to the copies. Two of the four complaints are about developers rather than throughput, and they matter for a reason that has little to do with speed. Two APIs in one project that treat object identity differently make it hard to reason about what a reference means at a given point in a job. That is the same confusion a central registry is meant to clear up when several agents speak different skill languages. A flag whose name promises reuse but delivers something else is worse, because it plants the wrong mental model about how long a reference stays valid.

Three modes, and the switch that controls them

Rather than turn copying off everywhere, FLIP-21 defines three modes and lets users choose where to sit on the safety and performance line.

ModeWhat it doesWhat it costs
DEFAULTCreates new objects only during deserialization, then passes them along without copyingProposed to become the new standard for the DataStream and DataSet APIs
COPY_PER_OPERATORCopies data between each operatorFlink's behavior today; safe, but slower
FULL_REUSEReuses objects wherever it canThe fastest option; demands the most care from user code

DEFAULT is the mode the proposal expects to become the new standard for both the DataStream and DataSet APIs. It confines the only unavoidable copy to a single point, deserialization, and lets objects travel untouched from there. The other two modes bracket it. COPY_PER_OPERATOR is what Flink does today. FULL_REUSE pushes reuse as far as it will go, buying speed while moving the burden of handling shared references onto the functions that receive the objects. The risk is uneven: COPY_PER_OPERATOR is slow but forgiving, while FULL_REUSE fails in ways that depend entirely on how carefully the surrounding code handles references. It is the same kind of bargain quantization strikes when it buys a smaller footprint at the cost of accuracy.

A related configuration switch, pipeline.object-reuse, defaults to false. Setting it to true lets Flink reuse objects internally for deserialization and for passing data into user functions. The proposal's own notes on the switch read as a short version of the trade: it reduces object creation and garbage collection overhead, but functions have to handle reused objects correctly, references are not guaranteed to stay valid after a function call returns, and the setting needs thorough testing before it goes anywhere near production. The goal is a familiar one: strip out overhead that no longer earns its keep, the way Blast Radius buries spent context so nothing keeps paying for it.

Migration: clean break or backward compatibility

The harder question is how existing pipelines reach a new default. Two migration approaches sit on the table. The community leans toward the first, the larger change up front but the cleaner result afterward.

The second worry is what happens to applications that already rely on the current copying behavior. The proposal treats that group as small and notes that those users can keep the old mode through configuration, so it is not counted as a major obstacle. The mailing-list discussion has been broadly positive. No availability target or release date has been set. That pull toward keeping the old path alive is the same instinct behind a file format built to stay openable regardless of what happens to the tool that made it.

For teams running Flink today, the immediate change is close to nothing. Until a new default arrives, the copy-at-every-operator rule stands and pipeline.object-reuse stays off. A safety default can keep costing long after the conditions that justified it have shifted. It moves only when someone measures the bill and argues for the change.

Get the tech essentials in 3 minutes every morning

One email, every weekday, with what actually matters in AI and tech.