Apicurio Registry as an Apache Iceberg REST Catalog
Apicurio Registry 3.2.0 now implements the Apache Iceberg REST Catalog API, turning your schema registry into a table catalog for Spark, Trino, DuckDB, and more. One service for both schema governance and lakehouse metadata.
Apache Iceberg needs a catalog. Every query engine – Spark, Trino, DuckDB, ClickHouse, Flink – needs to discover where Iceberg tables live and how to atomically commit changes to them. Starting with Apicurio Registry 3.2.0, we’ve implemented the Iceberg REST Catalog specification, so your schema registry can also serve as your Iceberg catalog.
Full deep dive article with architecture details and examples: distributed-deep-dives/iceberg-catalog-registry
Why This Matters
Most organizations using Iceberg already run a schema registry for their Kafka topics. Adding a separate Iceberg catalog means another service to deploy, monitor, and secure. With Apicurio Registry, you get both in one Quarkus application.
The mapping is natural: Iceberg namespaces become Registry groups, tables become artifacts (type ICEBERG_TABLE), and each commit creates a new immutable artifact version. No new storage abstractions were needed – the implementation is a translation layer on top of the existing Registry storage.
The Architecture
The Iceberg REST Catalog API is exposed at /apis/iceberg/v1 with 14 endpoints:
- Namespace operations – Create, list, load, drop, update properties
- Table operations – Create, list, load, drop, rename
- CommitTable – Atomic metadata updates with optimistic concurrency control
apicurio.features.experimental.enabled=true
apicurio.iceberg.enabled=true
apicurio.iceberg.warehouse=s3://my-bucket/warehouse
CommitTable and Concurrency
The most critical endpoint is CommitTable, which implements Iceberg’s optimistic concurrency protocol:
- Load current table metadata and record the version order
- Validate requirements (assertions about current state)
- Apply updates atomically to produce new metadata
- Store as a new artifact version with a version-order guard
If another writer committed between steps 1 and 4, the version-order check fails and returns HTTP 409. The Iceberg SDK handles retry automatically.
# Evolve a table schema atomically
curl -X POST http://localhost:8080/apis/iceberg/v1/default/namespaces/analytics/tables/events \
-H "Content-Type: application/json" \
-d '{
"requirements": [
{"type": "assert-current-schema-id", "current-schema-id": 0}
],
"updates": [
{
"action": "add-schema",
"schema": {
"type": "struct",
"schema-id": 1,
"fields": [
{"id": 1, "name": "id", "required": true, "type": "long"},
{"id": 2, "name": "event_type", "required": true, "type": "string"},
{"id": 3, "name": "ts", "required": true, "type": "timestamp"},
{"id": 4, "name": "source", "required": false, "type": "string"}
]
}
},
{"action": "set-current-schema", "schema-id": 1}
]
}'
Query Engine Integration
Any engine supporting the Iceberg REST Catalog spec works out of the box:
Spark:
spark.conf.set("spark.sql.catalog.apicurio", "org.apache.iceberg.spark.SparkCatalog")
spark.conf.set("spark.sql.catalog.apicurio.type", "rest")
spark.conf.set("spark.sql.catalog.apicurio.uri", "http://localhost:8080/apis/iceberg/v1")
Trino:
connector.name=iceberg
iceberg.catalog.type=rest
iceberg.rest-catalog.uri=http://localhost:8080/apis/iceberg/v1
DuckDB:
ATTACH 'http://localhost:8080/apis/iceberg/v1' AS apicurio (TYPE ICEBERG);
The Bigger Picture
The most interesting use case is schema convergence: managing the Avro schema for your Kafka topic and the Iceberg table schema for your lakehouse in the same registry. One governance layer for both your streaming and batch data infrastructure.
The feature is experimental in 3.2.0. Views support, credential vending, and query engine compatibility testing are planned for upcoming releases. Try it and let us know what you think – the implementation is young enough that your feedback will shape it.
Full article with Docker Compose setup, curl examples, and architecture details: distributed-deep-dives/iceberg-catalog-registry