> So I'd separate two things: deprecating in V4 (signal and direction, safe
to do now) versus forbidding equality-delete writes (gated on the
engine-agnostic path being ready). I'm only proposing the first for V4.

I thought we wanted to forbid equality-delete writes for v4 tables, which
would really simplify the v4 adaptive metadata tree along with other
benefits that Huaxin already outlined,

> deprecation path in v4

I heard the Kafka connector in the Iceberg repo doesn't produce equality
deletes. We would need to migrate the Flink sink to leverage the index to
produce DVs only in v4.

On Wed, Jul 15, 2026 at 12:13 PM huaxin gao <[email protected]> wrote:

> Thanks Max and Manu.
>
> Max, thanks for the added detail. It's a good point that the index in
> ConvertEqualityDeletes is persisted in Flink state (RocksDB) and updated
> incrementally. That strengthens the case, since it shows the key to
> position index is already durable, just scoped to Flink today. And your
> closing point is exactly the plan I have in mind: deprecate equality
> deletes in V4, and once the spec has an index, persist that PK index into
> Iceberg so it can be shared across engines.
>
> Manu, good question on how this works in practice. To be clear, I'm
> proposing "deprecated but permitted," not removal. In V4, writers
> (including Kafka Connect) could keep emitting equality deletes and readers
> would keep applying them. Deprecation just declares deletion vectors the
> going-forward mechanism and stops new investment in equality deletes. So V4
> would not be gated on the index landing.
>
> On the cleanup path today: ConvertEqualityDeletes runs against the table,
> not a specific writer, so a Kafka Connect pipeline can already be cleaned
> up. It keeps writing equality deletes, and a standalone Flink
> ConvertEqualityDeletes job converts them to DVs. The one friction is that
> the conversion runtime is Flink today, so a Kafka-only shop would have to
> run Flink just for maintenance. A Spark action would be a natural follow-up
> here, since Spark is the usual Iceberg maintenance engine and most batch
> shops already run it.
>
> Longer term, the next step is to persist the key to position index into
> Iceberg. Once it's shared, engines can look up positions and write DVs
> directly at write time, so a writer can stop producing equality deletes
> entirely, and neither the Flink job nor a Spark action needs to rebuild the
> index each run. Each engine (Kafka Connect, Spark, Flink) would adopt
> write-time DVs on its own schedule; until then it keeps writing equality
> deletes and relies on background conversion. So V4 deprecation doesn't
> require re-implementing every writer up front.
>
> So I'd separate two things: deprecating in V4 (signal and direction, safe
> to do now) versus forbidding equality-delete writes (gated on the
> engine-agnostic path being ready). I'm only proposing the first for V4.
>
> Thanks,
> Huaxin
>
> On Wed, Jul 15, 2026 at 3:10 AM Manu Zhang <[email protected]>
> wrote:
>
>> Hi Huaxin,
>>
>> +1 for deprecating equality deletes, but how would this deprecation work
>> practically in V4?
>> As Max pointed out, we still lack an engine-agnostic solution for
>> streaming use cases. For example, how would we handle equality deletes
>> written by Kafka Connect?
>> While the index proposal looks promising, I don't see a clear path for
>> deprecating equality deletes in V4 before that index work actually lands.
>>
>> Thanks,
>> Manu
>>
>>
>> On Wed, Jul 15, 2026 at 5:30 PM Maximilian Michels <[email protected]>
>> wrote:
>>
>>> Hi Huaxin,
>>>
>>> Thanks for reviving the discussion on deprecating equality deletes.
>>> Equality deletes are the number one pain for streaming use cases. Many
>>> users give up when they see the merge-on-read costs, or they build
>>> custom solutions which move them further away from core Iceberg. That
>>> said, we've made great progress since the initial conversation in
>>> 2024.
>>>
>>> Just to add what you said: The index we maintain in
>>> ConvertEqualityDeletes is not ephemeral. The index is persisted in
>>> Flink's managed state (RocksDB). It is continuously updated as new
>>> data arrives and checkpointed periodically. However, even though the
>>> conversion works for data written by any engine, we currently require
>>> Flink for the conversion itself. Storing the index directly in Iceberg
>>> and enabling all engines access would be the next logical step towards
>>> a fully engine-agnostic solution.
>>>
>>> The reality is that we don't yet have a working solution to avoid
>>> writing equality deletes across all engines, but given the recent
>>> progress, the proposed plan seems realistic. So +1 for deprecating
>>> equality deletes in V4.
>>>
>>> Cheers,
>>> Max
>>>
>>>
>>>
>>> On Tue, Jul 14, 2026 at 3:25 AM huaxin gao <[email protected]>
>>> wrote:
>>> >
>>> > Hi all,
>>> >
>>> > I'd like to restart the conversation about deprecating equality
>>> deletes, now in the context of the V4 spec.
>>> >
>>> > Background
>>> >
>>> > This isn't a new idea. Russell proposed deprecating equality deletes
>>> in V3 and removing them from the spec in V4, back in October 2024 in
>>> "[DISCUSS] - Deprecate Equality Deletes". The main blocker at the time was
>>> that equality deletes served real use cases (especially Flink streaming
>>> upserts) with no efficient alternative. Two developments since then make
>>> the V4 removal worth acting on now.
>>> >
>>> > Why equality deletes are costly
>>> >
>>> > Equality deletes are cheap to write but expensive to read: a reader
>>> must load the equality-delete files and join them against every candidate
>>> row in the delete's sequence-number range. Positional deletes skip that
>>> per-row join by marking exact positions, so they have always read faster,
>>> and V3 deletion vectors make them faster still, one compact bitmap per data
>>> file, applied by an O(1) position check, instead of V2's many
>>> position-delete files. So equality deletes' only real edge is the cheap
>>> write, and both background conversion and a write-time key-lookup index can
>>> recover that.
>>> >
>>> > Beyond performance
>>> >
>>> > Equality deletes also block other features. CDC and row lineage are
>>> effectively impossible while they are in use, because the true state of the
>>> table can only be determined with a full scan. That same property means
>>> differential structures such as materialized views and secondary indexes
>>> have to be fully rebuilt whenever an equality delete is added, rather than
>>> maintained incrementally. So removing equality deletes is close to a
>>> prerequisite for the index work to stay incrementally maintainable.
>>> >
>>> > Evidence the alternatives are practical
>>> >
>>> > 1. Converting equality deletes to DVs works today. Max Michels'
>>> ConvertEqualityDeletes maintenance task (16831, 16844, 16858, 16874, 16889,
>>> 16948) rewrites equality deletes into deletion vectors as a background
>>> Flink job: the writer keeps appending equality deletes to a staging branch,
>>> and the task converts them to DVs on the target branch so reads apply
>>> deletes by position. Notably, the task resolves each delete to a position
>>> using a primary-key index that it builds and maintains inside the job,
>>> demonstrating the full "key -> position -> DV" path end to end.
>>> >
>>> > 2. A persistent key-lookup index removes the need to write them at
>>> all. The secondary index spec we're working on (#16961) includes a
>>> key-lookup index mapping a key to its data file and row position. This is
>>> essentially the persistent, catalog-managed form of the index Max's task
>>> builds ephemerally. With it, a writer can resolve positions at write time
>>> and emit DVs directly, without ever producing an equality delete.
>>> >
>>> > How these two efforts fit together
>>> >
>>> > They're complementary, and they cover the two things we need to
>>> deprecate equality deletes:
>>> >
>>> > Migration (existing data): ConvertEqualityDeletes cleans up tables
>>> that already contain equality deletes, and supports writers that still emit
>>> them, converting them to DVs in the background.
>>> > Going forward (new writes): the persistent key-lookup index lets
>>> writers skip equality deletes entirely by looking up positions directly.
>>> > The connection is that Max's task already proves the core mechanism
>>> (resolve key -> position, write a DV); it just rebuilds a throwaway index
>>> each cycle. A durable, shared index both enables write-time elimination and
>>> removes that rebuild cost from the conversion path.
>>> >
>>> >
>>> > Proposal
>>> >
>>> > I propose that we deprecate equality deletes in V4. The blocker from
>>> 2024 was the lack of a viable alternative, and we now have the pieces:
>>> background conversion to DVs works today, and the key-lookup index gives us
>>> a path to eliminating them at write time. Deletion vectors should be the
>>> going-forward mechanism for row-level deletes and upserts, produced by
>>> background conversion now and directly by writers once the index is
>>> available. Readers would continue to support equality deletes for backward
>>> compatibility with existing V2/V3 tables.
>>> >
>>> > Migration path
>>> >
>>> > Existing tables keep working; readers continue to apply equality
>>> deletes.
>>> > ConvertEqualityDeletes (Flink) rewrites existing equality deletes into
>>> DVs so tables can be cleared of them over time.
>>> >
>>> >
>>> > I'd love people's thoughts, especially from those running large
>>> streaming-upsert workloads.
>>> >
>>> > Thanks,
>>> > Huaxin
>>>
>>

Reply via email to