<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw" -->

---
title: Iceberg V3 in Velox | daily.dev
description: The Velox Iceberg connector now supports most of Iceberg V3, added over the past six months. Deletion vectors work for both reading and writing, covering...
canonical: https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Iceberg V3 in Velox | daily.dev
og:description: The Velox Iceberg connector now supports most of Iceberg V3, added over the past six months. Deletion vectors work for both reading and writing, covering...
og:url: https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw
og:image: https://api.daily.dev/og/posts/Qx65fpfHw.png
og:image:alt: Iceberg V3 in Velox
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Iceberg V3 in Velox

**[Velox Engineering Blog](https://daily.dev/sources/velox)** · 9 min read · 0 upvotes · 0 comments

## Summary

The Velox Iceberg connector now supports most of Iceberg V3, added over the past six months. Deletion vectors work for both reading and writing, covering DELETE, UPDATE and MERGE. Row lineage, default values and new geospatial types work on read, while write defaults also work on write. Deletion vectors replace V2's positional delete files with a Roaring bitmap stored in a Puffin file. The team matched Iceberg Java byte for byte, fixing bugs like a wrong CRC-32 implementation and incorrect partition data on deletion vectors. Variant types, nanosecond timestamps, multi-argument transforms and table encryption remain unimplemented, and deletion vector benchmarks are still pending.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://velox-lib.io/blog/iceberg-v3>

## Questions this post answers

### How do Iceberg V3 deletion vectors differ from V2 positional delete files?

Iceberg V3 replaces V2's per-write positional delete files with a single deletion vector per data file: a Roaring bitmap of deleted row positions stored as a deletion-vector-v1 blob inside a Puffin file. The manifest entry records the blob's offset and length, so a reader makes one ranged read instead of opening and merging many delete files, and the spec caps it at one deletion vector per data file.

_Teams planning an Iceberg V3 migration can track connector support details like this on daily.dev._

### Why would reading an Iceberg deletion vector produce wrong row IDs after filtering?

Computing a row's _row_id from its position in the output batch gives wrong IDs once a deletion vector has removed rows, because the output index no longer matches the row's actual position in the file. The fix is to add a hidden row-number column and compute _row_id from that, rather than from the filtered batch index, whenever lineage columns are projected.

_Developers debugging row lineage bugs in Iceberg readers can follow implementation details like this on daily.dev._

### Why did my Iceberg deletion vector written by one engine fail to validate when read by another?

A common cause is a non-standard CRC-32 implementation: using folly::crc32 instead of zlib's crc32 skips the final inversion standard CRC-32 applies, so same-engine round trips pass but cross-engine files written by Spark or Java fail validation. Matching java.util.zip.CRC32 byte for byte, including the signed 32-bit key cap Java's RoaringPositionBitmap enforces, is necessary for interoperability.

_Engineers debugging cross-engine Iceberg compatibility issues can find implementation specifics like this on daily.dev._

## Similar posts on daily.dev

- [Advancing the Lakehouse with Apache Iceberg v3 on Databricks](https://daily.dev/posts/advancing-the-lakehouse-with-apache-iceberg-v3-on-databricks-6p6wf37qi) · databricks · 4 upvotes · 0 comments
- [Amazon S3 Tables now support all Apache Iceberg V3 data types](https://daily.dev/posts/amazon-s3-tables-now-support-all-apache-iceberg-v3-data-types-nkjnu2oqj) · AWS · 0 upvotes · 0 comments
- [The Battle for Compute: Unlocked by Iceberg V3 and Snowflake Interoperability](https://daily.dev/posts/the-battle-for-compute-unlocked-by-iceberg-v3-and-snowflake-interoperability-o4erztdpv) · Snowflake Community · 0 upvotes · 0 comments
- [Decision path for position deletes with row data during an Iceberg 1.12 upgrade](https://daily.dev/posts/decision-path-for-position-deletes-with-row-data-during-an-iceberg-1-12-upgrade-vvndcyiia) · Dremio Blog · 4 upvotes · 0 comments

---

Tags: [#big-data](https://daily.dev/tags/big-data), [#data-engineering](https://daily.dev/tags/data-engineering), [#apache-iceberg](https://daily.dev/tags/apache-iceberg)

[View this post on daily.dev](https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Iceberg V3 in Velox","url":"https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw"},"datePublished":"2026-10-30T22:35:31.046Z","dateModified":"2026-10-30T22:35:59.995Z","description":"The Velox Iceberg connector now supports most of Iceberg V3, added over the past six months. Deletion vectors work for both reading and writing, covering...","image":"https://media.daily.dev/image/upload/s--0_ODbtD2--/f_auto/v1722860399/public/Placeholder%2008","thumbnailUrl":"https://media.daily.dev/image/upload/s--0_ODbtD2--/f_auto/v1722860399/public/Placeholder%2008","isAccessibleForFree":true,"articleSection":"Velox Engineering Blog","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Velox Engineering Blog","logo":"https://media.daily.dev/image/upload/s--Cmr7TiDP--/f_auto,q_auto/v1791720353/logos/velox?_a=BAMAMicg0","url":"https://daily.dev/sources/velox"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"big-data,data-engineering,apache-iceberg","timeRequired":"PT9M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Velox Engineering Blog","item":"https://daily.dev/sources/velox"},{"@type":"ListItem","position":3,"name":"Iceberg V3 in Velox"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/iceberg-v3-in-velox-qx65fpfhw#faq","mainEntity":[{"@type":"Question","name":"How do Iceberg V3 deletion vectors differ from V2 positional delete files?","acceptedAnswer":{"@type":"Answer","text":"Iceberg V3 replaces V2's per-write positional delete files with a single deletion vector per data file: a Roaring bitmap of deleted row positions stored as a deletion-vector-v1 blob inside a Puffin file. The manifest entry records the blob's offset and length, so a reader makes one ranged read instead of opening and merging many delete files, and the spec caps it at one deletion vector per data file. Teams planning an Iceberg V3 migration can track connector support details like this on daily.dev."}},{"@type":"Question","name":"Why would reading an Iceberg deletion vector produce wrong row IDs after filtering?","acceptedAnswer":{"@type":"Answer","text":"Computing a row's _row_id from its position in the output batch gives wrong IDs once a deletion vector has removed rows, because the output index no longer matches the row's actual position in the file. The fix is to add a hidden row-number column and compute _row_id from that, rather than from the filtered batch index, whenever lineage columns are projected. Developers debugging row lineage bugs in Iceberg readers can follow implementation details like this on daily.dev."}},{"@type":"Question","name":"Why did my Iceberg deletion vector written by one engine fail to validate when read by another?","acceptedAnswer":{"@type":"Answer","text":"A common cause is a non-standard CRC-32 implementation: using folly::crc32 instead of zlib's crc32 skips the final inversion standard CRC-32 applies, so same-engine round trips pass but cross-engine files written by Spark or Java fail validation. Matching java.util.zip.CRC32 byte for byte, including the signed 32-bit key cap Java's RoaringPositionBitmap enforces, is necessary for interoperability. Engineers debugging cross-engine Iceberg compatibility issues can find implementation specifics like this on daily.dev."}}]}
```

