Writing · Lakehouse format
V3 changed the boundary conditions. V4 is changing them again.
The original V2-era case for Iceberg in security operations rested on five claims: hidden partitioning, time travel, schema evolution without rewrites, ACID transactions, and vendor-neutral compatibility with 20+ query engines. All five still hold. What V3 changed was the boundary conditions — the specific places where the V2 case had real weaknesses that critics could point to. V4, still in design and discussion as of mid-2026, will move the boundaries again. The thesis doesn't change; the soft spots keep getting smaller.
What V3 changed
Five features that matter for security.
Puffin-based deletion vectors.
V3 introduces Puffin-based deletion vectors as the merge-on-read mechanism, replacing V2's position-delete and equality-delete files. A deletion vector is a compact bitmap stored in a Puffin file alongside the data file, marking which rows are logically deleted without rewriting the data file itself.
The security implications are direct. GDPR right-to-erasure becomes a metadata operation.
In V2, a DELETE WHERE user_id = 'X' query wrote one or more position-delete files, and those
files then needed to be compacted away on a maintenance schedule. The user's data physically remained in
the data files until compaction; the auditor saw "deleted" in the table query, but the bytes were still
on disk. V3 deletion vectors make the delete a metadata bitmap update. Compaction still cleans up
eventually, but the operational urgency is much lower because there's no delete-file accumulation
problem.
Streaming sinks become cheaper. Streaming pipelines that write to Iceberg with merge-on-read historically accumulated delete files at a rate proportional to the update rate, which forced aggressive compaction schedules to keep query performance acceptable. With deletion vectors, the per-row update cost drops materially and compaction becomes a less frequent maintenance operation.
And the "Iceberg MoR is less mature than Delta" critique closes. Delta Lake has used Puffin-based deletion vectors for longer and has more production mileage with them, but the capability gap between Iceberg and Delta on merge-on-read maturity is now closed. The remaining difference is production-track-record-years, not architectural mechanics.
What deletion vectors don't fix: the write amplification of large bulk updates. If you're rewriting half the rows in a partition, you're still rewriting half the data file — deletion vectors are only a win for sparse updates and deletes. They also don't change the latency floor for detection-tier workloads; even with V3, Iceberg is still a hunting/analysis-tier format, not a detection-tier surface. Sub-second detection still belongs in the streaming layer, not in the lakehouse query engine.
Variant type — semi-structured data without flattening.
V3 introduces a Variant type for storing semi-structured data — typically JSON — with native predicate pushdown and field extraction. The corresponding Parquet Variant type was ratified in October 2025 and Iceberg V3 is one of the first table formats to adopt it.
Security log ingestion is the canonical Variant use case. Almost every security log type that started life as JSON (CloudTrail, Kubernetes audit, Azure Activity, Okta system logs, GitHub audit, Slack audit) has the property that field presence carries information. The classic example:
{
"userIdentity": {
"sessionContext": {
"attributes": {
"mfaAuthenticated": "true"
}
}
}
}
In CloudTrail, the mfaAuthenticated field is only present when MFA was used. If you flatten
this to a wide column schema, you lose the distinction between "the field was absent" (no MFA) and "the
field was NULL" (which never happens in CloudTrail but is what your flat schema produces). A detection
rule checking WHERE mfaAuthenticated = false returns zero results and silently breaks.
That's not a hypothetical — it's the failure mode the
flattening anti-pattern essay documents.
V3 Variant fixes this by construction. You store the entire userIdentity object as a Variant
column; the absence-vs-NULL distinction is preserved natively; predicate pushdown still works through
variant_get() calls; and the same query works across any V3-aware engine without ETL
rewrites.
V2 alternatives existed, all imperfect. ClickHouse Nested types worked inside ClickHouse but weren't portable across engines. Storing as a JSON STRING column with manual parsing worked but lost predicate pushdown and forced every query to parse the JSON. Flattening and accepting the absence-vs-NULL bug worked for some logs (where field presence doesn't carry information) but silently broke detections like the CloudTrail MFA case. V3 Variant is the cross-engine answer that none of the workarounds were.
Adoption caveat: Variant requires variant_get() and Variant-aware predicate
pushdown in the query engine. As of April 2026, support is uneven: Spark 4.1 has it, DuckDB has partial
support, Trino is rolling it out, Snowflake has its own native semi-structured type that maps to Variant
on read but not on write. By Q4 2026 this should be a non-issue; for now, verify your engine version.
Row-level lineage — row IDs + last-updated tracking.
V3 introduces row IDs and last-updated tracking at the row level. Every row in a V3 Iceberg table has a stable identifier and a last-modified timestamp tracked through metadata, without requiring the data files themselves to carry the information. This is the V3 feature with the largest set of net-new use cases that didn't exist in V2 at all.
CDC-from-Iceberg without external metadata. In V2, building a change feed from an Iceberg table required either snapshot diffing (compute the difference between snapshot N and N+1) or external metadata tracking via Debezium-style log scraping. Both are operationally heavy. V3 row lineage lets you query "all rows that changed since timestamp T" directly from Iceberg metadata, with no external infrastructure.
dbt incremental without watermark columns. The standard dbt incremental pattern uses a
watermark column (WHERE event_time > (SELECT MAX(event_time) FROM {{ this }})) to
identify new rows. This pattern silently drops late-arriving events that arrive after the next dbt run.
V3 row lineage lets you use the row's last-updated timestamp instead, which is robust to late arrivals
because the lineage timestamp is the processing time, not the event time.
Audit trail integrity for compliance. For tables under regulatory audit (PCI-DSS, HIPAA, GDPR), being able to point at a specific row and say "this row was last modified at T by transaction X" without external infrastructure is a compliance simplification. V2 required either external audit logs or full table snapshots; V3 makes this a metadata query.
Incremental detection re-firing. If a detection rule changes (the SOC team adds a new IOC, refines a regex, fixes a bug), you typically want to re-evaluate it against historical data — but only against events that haven't already been evaluated by the new rule version. V3 row lineage lets you express this as "evaluate rule version 1.7 against rows whose last-modified timestamp is newer than the rule version 1.7 deployment time."
Adoption caveat: Row lineage is the V3 feature with the least mature engine support as of April 2026. Spark 4.1 has experimental support; Trino and DuckDB have it on the roadmap; Snowflake hasn't committed to a timeline. The use cases above are all real but most won't be production-deployable until 2027.
Default values for columns.
V3 allows you to add a column with a non-null default value as a metadata-only operation. In V2, adding a column with a default required either rewriting the entire table or accepting that the new column would read as NULL for old rows.
Schema evolution for security log tables is constant. New OCSF schema versions, new vendor field
additions, new internal enrichment columns — most security tables see a schema evolution event every few
weeks. In V2, adding a column with a default like WITH DEFAULT 'unknown' required
reprocessing the entire table to backfill the default into existing rows. For petabyte-scale tables,
that was a multi-day, multi-thousand-dollar operation.
V3 makes this a metadata-only operation: the default is recorded in the table schema and applied at read time for rows that don't have an explicit value. The data files are untouched. What it doesn't fix: default values still don't help if you need to backfill existing rows with computed values (e.g., "compute risk_score for all CloudTrail events from the last 90 days using the new model"). That's a write operation, not a schema evolution, and V3 doesn't change it.
Other V3 features (brief).
- Geospatial type — useful for IoT and physical security data with location attributes; not load-bearing for typical security-data use cases.
- Timestamp(nanos) — nanosecond-precision timestamps. Marginal for most security data (microsecond is fine), but matters for EDR and packet-capture ordering claims that some lakehouse architectures make loosely.
- Unknown type — forward-compatibility primitive that lets V3 readers handle columns of unknown future types gracefully. Mostly an ecosystem-stability feature, not directly user-facing.
- Encryption improvements — incremental tightening of the V2 encryption story. Useful for compliance-sensitive deployments but doesn't change the security architecture conversation meaningfully.
What didn't change
A long list of things V3 is overclaimed on.
V3 doesn't change the latency floor. Iceberg is still a hunting/analysis-tier format. V3 deletion vectors make MoR cheaper, but they don't make Iceberg a detection-tier surface. Sub-second detection still belongs in the streaming layer (Flink, RisingWave, pipeline-based detection), not in the lakehouse query engine.
V3 doesn't fix the Kafka/Iceberg storage primitive mismatch. The K.S.I. proxy pattern shows that V3 enables proxy-layer integrations that look like a unified log, but the underlying storage primitives still serve opposing access patterns.
V3 doesn't replace OCSF normalization. Variant gives you a cross-engine way to store semi-structured logs without losing field-presence semantics, but OCSF still matters for cross-vendor query consistency. The right pattern is "V3 Variant for raw retention + OCSF projection for normalized query layer," not "V3 Variant instead of OCSF."
V3 doesn't eliminate the case for Delta Lake. Delta still has more production mileage on the deletion-vectors mechanism, more mature CDC tooling, and the deepest integration with the Databricks ecosystem. For Databricks-committed teams or teams with strict risk-aversion to "the V3 spec is two months old," Delta remains a defensible choice. What V3 changes is that the capability gap is closed; the remaining gap is production-track-record. See the Iceberg vs Delta essay for the full decision framework.
V3 doesn't make the MOAR architecture thesis wrong. If anything, it strengthens it. The MOAR pattern is "lakehouse + streaming + multi-engine query," and V3 makes the lakehouse layer materially more capable without changing the streaming or query-engine layers. The architecture diagram doesn't change; the labels on the lakehouse-layer arrows get smaller.
Where the spec may not land cleanly
Two places to watch for V3 disappointment.
Variant type engine fragmentation.
V3 Variant is purpose-built for cross-engine portability, but the engine ecosystem isn't standardizing
on the same surface API for it. Spark uses variant_get(). DuckDB has its own JSON-like
syntax. Snowflake's existing semi-structured VARIANT type maps loosely to V3 Variant but
not exactly. Trino is debating between several proposals.
The risk: by the time engine support is "complete" in late 2026, the query syntax for Variant fields will be different across engines, defeating the cross-engine portability that's the whole point. Teams will end up with "Variant in the storage layer, but per-engine query rewriting in the application layer" — most of the work without most of the benefit. Watch for an Apache Iceberg community spec that pins down a canonical Variant access syntax in the second half of 2026.
Row lineage and CDC production-readiness.
The CDC-from-Iceberg use case is the one most worth being excited about, but it's also the one where the engine support gap is the largest. As of April 2026, only Spark 4.1 has experimental row-lineage support. Trino and DuckDB are on the roadmap. Snowflake hasn't committed.
The risk: production CDC consumers (Debezium, Fivetran, Hightouch, RisingWave's Iceberg source) will need a year or more to integrate V3 row lineage into their existing CDC plumbing. The leading indicator to watch is a production reference deployment that uses row lineage to feed a downstream system without snapshot diffing or external metadata. As of April 2026, none has surfaced publicly. If that hasn't happened by Q4 2026, V3's CDC story will have shifted from "promising" to "spec-only."
V4 — already shifting the boundary conditions again
V4 is in design now. The features that matter for security.
V4 has not been formally adopted as of mid-2026. The spec is in active design and discussion. None of the proposals below are merged yet, and the engine-support gap will be larger for V4 than it is for V3 today. That said, several proposals are specific enough to evaluate against the security workload — and a few of them close the next set of boundary conditions in ways V3 didn't.
Single-file commits.
The proposal consolidates all metadata changes into one file per commit, reducing I/O overhead for high-write workloads. The current per-commit footprint involves multiple manifest files plus a metadata JSON; V4 collapses that to one.
Security-data relevance: streaming security ingest workloads frequently commit at sub-second cadences under sustained load — agent telemetry from a 50,000-endpoint EDR fleet, NDR alerts at network speed, identity-provider event streams. Each commit's metadata I/O is a small operational tax that compounds across thousands of commits per minute. Single-file commits substantively reduce that tax, which makes sustained high-write streaming sinks materially cheaper. The streaming-ingest cost story for V4 looks different than it does for V3.
Parquet for metadata.
V3 metadata files use Avro encoding. V4 proposes replacing Avro with Parquet for manifest and metadata files, enabling columnar reads of the metadata itself — engines only load the metadata fields they need per query, not the full manifest blob.
Security-data relevance: petabyte-scale security tables have proportionally large manifest catalogs. Querying a 2-PB Iceberg table currently means reading manifest files that are themselves substantial in size, even when the query only needs partition-level pruning. Parquet-encoded metadata lets the engine do columnar-style pushdown on the manifest itself, accelerating query planning. The improvement scales with table size — small tables see little benefit, but security data lakes that retain six years of Reg-SCI or 17a-4 data are exactly the workload where this matters.
Enhanced column statistics.
V4 proposes a redesigned statistics format with type information, nested-field support, and richer structure for cost-based optimizers. The current V3 statistics are limited to top-level columns with basic min/max/null-count metadata; V4 extends this to nested-field statistics (which compose with the Variant type from V3 directly) and adds richer histograms.
Security-data relevance: detection queries are heavily predicate-driven and selective on nested fields.
A CloudTrail query checking userIdentity.sessionContext.attributes.mfaAuthenticated currently
can't push the predicate down to file pruning because V3 statistics don't track nested-field min/max. V4
statistics let the engine prune entire files based on nested-field predicates, which is the single biggest
query-planning win for the Variant-stored security log workload.
Efficient column updates.
Péter Váry's proposal targets wide tables — tables with hundreds of columns where a typical update touches only a handful. The current V3 mechanism rewrites the entire row group for any column update; the proposal allows per-column update granularity with smaller rewrite footprints. POC benchmarks are underway as of mid-2026 for both Iceberg-native and Parquet-native approaches.
Security-data relevance: OCSF-shaped security tables are exactly the wide-table case. OCSF Network Activity events have dozens of optional fields, most NULL for any given row. Enriching a single field (adding a threat-intel match, an asset-criticality lookup, a user-risk score) currently rewrites the entire row group. V4 column updates make incremental enrichment workflows substantively cheaper — which changes the economics of "should we materialize enrichments at ingest or compute them at query time" in favor of materialization.
Catalog-managed metadata.
The V4 metadata.json optionality direction — treating catalog-managed metadata as a first-class supported mode, while preserving static-table portability through explicit opt-in semantics — is described in the Iceberg community as "the defining specification conversation" for V4. Catalog-managed metadata moves the authoritative version of the table state out of the metadata.json file and into the catalog service (Polaris, Unity, Nessie, Glue), which becomes the source of truth.
Security-data relevance: governance and lineage workflows benefit when the catalog is authoritative. Currently, every Iceberg writer has to coordinate metadata.json updates with the catalog, which is where most "I committed but the catalog hasn't seen it yet" race conditions originate. Catalog-managed mode eliminates that race by construction. The cost is that static-table portability — moving a table by copying files — becomes opt-in rather than the default. For security data that's largely never moved between storage backends, this is a clean trade.
Relative paths.
V4 proposes replacing absolute file paths with relative URIs in the metadata. The current V3 metadata records absolute S3 (or HDFS, or local) paths for every data file; moving a table to a different bucket requires rewriting all the metadata. V4 relative paths let the catalog or query engine resolve paths at read time, simplifying cross-region replication, backup restoration, and on-prem to cloud migrations. For security data subject to data-residency requirements (DORA, GDPR), this is a quiet but meaningful operational improvement.
The meta-observation
The cadence is the load-bearing fact.
Iceberg ships substantively every twelve to eighteen months. V2 in 2022, V3 in 2025, V4 under design now for likely 2026–2027 adoption. Each tranche closes a different set of boundary conditions. V3 closed deletion vectors and Variant and row lineage. V4 will close metadata I/O cost, nested-field statistics, and catalog authority. V5 will close something else — the projects already filing as v5 candidates include richer compression, time-series-native partitioning, and tighter Variant predicate semantics.
The pattern matters more than any single version. A security architecture that bets on Iceberg is betting on the cadence — on the project shipping substantive improvements at a predictable rhythm with backward-compatible read semantics. That bet has paid off through V1 → V2 → V3. The V3 → V4 transition is the third proof point.
The case against was always "what if it stalls?" — what if V3 is the high-water mark, what if the community fragments, what if a competing format wins. V4's design momentum is the strongest evidence against that case so far. The boundary conditions for the V2 case kept getting smaller. The boundary conditions for the V3 case are getting smaller too.
Iceberg V3 today. V4 on the horizon. The architecture stays the same.
Lakehouse-format decisions are evaluated against the actual workload, not against the marketing claim. The Matrix scores Iceberg, Delta, Hudi, and the proprietary table formats with versioned criteria across engine portability, MoR maturity, CDC story, governance, and operational ergonomics.