I understood "deprecate equality deletes" as not forbidding engines to write them, but rather discouraging them. IMHO this is long overdue, but it is also a very soft transition. Perhaps too soft, because it doesn't give engines who write them a real incentive to stop writing equality deletes.
Engines will likely be quicker to move away from writing equality deletes if we disallow writing them in V4. Regardless, we will have to support reading equality deletes for V2 and V3 tables. I'm leaning more towards removing equality deletes for V4 tables, but I would like to hear what others think. -Max On Wed, Jul 15, 2026 at 10:03 PM Steven Wu <[email protected]> wrote: > > > 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
