Iceberg Data Platform · October 2026

An open lakehouse you actually own.

Apache Iceberg as the table format, with every other building block open source, replaceable, and running on a single laptop.

Sander de Wildt
Apache Iceberg · Polaris · Keycloak
RustFS · marimo · DuckDB
Intro

Hi,

Knowledge about Apache Iceberg is not spreading as easily as it should. Before you can start, you need quite a few components: a catalog, object storage, identity, an engine and a place to work. Vendors make that part easy, and that is usually where vendor lock-in starts.

So I built a small platform that shows the other route: every building block open source, running on one laptop with a single command. Apache Iceberg is a very good choice for autonomy and portability.

Three things to land today
  1. How Iceberg actually works, and why it is not a platform like Snowflake.
  2. What a fully open source stack gives us: autonomy, portability and no lock-in.
  3. A demo of one grid sensor data product: loaded by a team, given meaning by a coding agent, shared with another team, listed in a data catalog and asked about in a chat.
Intro · How I build

Five principles behind every choice

1 · Clean UXOne Design System. From sign-in to a notebook in a few clicks, one design language in both portals, and a Getting started page in each.
2 · API firstThe portal is just a client. Every button is a documented route with an OpenAPI schema, so a script can do everything a person can.
3 · AI nativeAgents are first-class users. Both portals serve MCP with the user's own identity, data products carry their meaning in a semantic model, and agent skills ship with the installer.
4 · Open sourceNo licences. Every building block is Apache-2.0 or MIT, and so is the platform. No vendor account and no trial clock.
5 · Loosely coupledOpen interfaces between the components. Iceberg REST, S3, OIDC and MCP, so you can replace one block without touching the others. Bigger capabilities come as extensions behind one contract, so the core stays small.
The one-liner

Apache Iceberg is doing for data what open APIs did for applications.

REST and OpenAPI made it possible for any service to talk to any application. Apache Iceberg does the same for structured data: one open table standard, so no single engine owns your data.

Sander de Wildt
01

How Apache Iceberg works

And why it is not a database platform like Snowflake.

01 · Iceberg

Iceberg is a specification, not a product you buy

Snowflake · Databricks · BigQuery
  • One vendor delivers storage, compute, catalog, security and the UI as a single product.
  • Your tables live in the vendor's format and in the vendor's account.
  • You rent the capability, so leaving means migrating the data and everything built around it.
Apache Iceberg
  • An open specification for how table data and metadata are laid out in object storage.
  • Data files are plain Parquet and metadata is JSON and Avro, so no server owns them.
  • You bring the catalog, the engines, the storage and the identity provider, and each one stays replaceable.
01 · Iceberg

Start with what you already know: PostgreSQL

Imagine a simple table: columns, rows and SQL queries.

Who does the job?A regular PostgreSQL tableAn Iceberg table in this platform
Run your SQLThe PostgreSQL server.An engine such as DuckDB or Spark.
Find the table
and check access
PostgreSQL's system catalogs and permissions.Polaris: the table's name, permissions and current metadata location.
Describe the columnsPostgreSQL's system catalogs.An Iceberg metadata file in object storage.
Store the rowsFiles managed and read by PostgreSQL.Parquet files in a bucket, read directly by the engine.
Scale storage and computeOne server: more data or more queries means a bigger server.Separate: storage grows in the bucket, and each engine brings its own compute.
01 · Open source

Every building block is open source

CapabilityComponentVersionLicenseSwappable for
Table formatApache Iceberg (PyIceberg)spec v2 and v3 · 0.12Apache-2.0The standard itself, engines come and go.
Catalog and permissionsApache Polaris1.8.0Apache-2.0Lakekeeper, Nessie, Gravitino, Unity Catalog OSS, AWS Glue
Identity (OIDC)Keycloak26.8.0Apache-2.0Entra ID, Okta, any OIDC provider
Object storage (S3 API)RustFS1.0.1Apache-2.0AWS S3, MinIO, Ceph, Cloudflare R2, on-prem
Catalog metadata storePostgreSQL18PostgreSQLManaged Postgres anywhere
Notebooksmarimo0.25.1Apache-2.0Jupyter, VS Code, any Python client
Query engineDuckDB with the iceberg extension, reads and writes1.5.6MITTrino, Spark, Flink, Polars, ClickHouse
Portals and APIFastAPI, Python 3.140.143MITBuilt here, deliberately thin.
Semantic modelsApache Ossie (incubating), stored by Polarisspec 0.2.0Apache-2.0Any tool that reads the open specification
Agent interfaceModel Context Protocol, Python SDK2.3MITAny MCP client: Claude Code, IDEs, a custom agent
Conversational BI (extension)Pydantic AI, CopilotKit, Chart.js, DuckDB2.55 · 1.79 · 4.5 · 1.5.5MITAny LLM provider: OpenAI, Anthropic, Gemini, Bedrock
dbt pipelines (extension)dbt v2 OSS on DuckDB2.0.8 · 1.5.5Apache-2.0Any dbt adapter for an Iceberg engine
Ingestion (extension)dlt with its Iceberg destination1.31Apache-2.0Airbyte, Meltano, any Iceberg REST writer
Data catalog (extension)OpenMetadata, fed through its REST API2.0.5Apache-2.0DataHub, Unity Catalog OSS, Apache Atlas
02

The platform

Teams, databases, AI agents and extensions, on one identity and with each user's own permissions throughout.

02 · Platform

Architecture

Administrator Team member AI agentMCP client Admin portal :3000FastAPI · teams, users, databases User portal :3002FastAPI · catalog, notebooks KeycloakOIDC · people and agents Apache PolarisIceberg REST · semantic models PostgreSQL 18catalog metadata only RustFS (S3)one bucket per database marimo runtimecontainer per user session /mcp bucket and IAM provisioning (S3 API) token validation (JWKS) vended, table-scoped credentials ExtensionsCBI · dbt · dlt · OpenMetadata Extension Bridge/bridge/v1 · contract 0.1.1
02 · Platform

Polaris RBAC per team: the high-level view

Team-level view of a 12-person Voltara Energy class. The company has three teams, grid-planning, asset-management and outage-response, each with four members: one admin and three writers. Each team owns a production and a development catalog. In both catalogs, the admin gets the admin catalog role and the writers the writer catalog role. The trainer holds the Keycloak platform-admin role and, through their own platform user, the reader catalog role in every team. Level Voltara Energy · 12 participants Companyone installation Teammembers, one role each Catalog roleadmin · writer · reader Catalogone per database · own bucket has role becomes on Voltara Energygrid operator and energy supplier · voltara.example the trainer · platform-adminKeycloak role · reader in every team grid-planning4 members · 1 admin · 3 writers asset-management4 members · 1 admin · 3 writers outage-response4 members · 1 admin · 3 writers admin ×1 · writer ×3reader ×1 · the trainer admin ×1 · writer ×3reader ×1 · the trainer admin ×1 · writer ×3reader ×1 · the trainer admin ×1 · writer ×3reader ×1 · the trainer admin ×1 · writer ×3reader ×1 · the trainer admin ×1 · writer ×3reader ×1 · the trainer grid-capacityproduction grid-capacity-scenariosdevelopment grid-assetsproduction maintenance-forecastsdevelopment outage-eventsproduction outage-analyticsdevelopment
02 · Platform · Team workspace

Team administrators run their own databases

User portal Databases page with the create database form filled in
02 · Platform · AI agents

The catalog, for an AI agent

claude mcp add --transport http \
  --client-id iceberg-mcp --callback-port 3010 \
  iceberg-user http://localhost:3002/mcp
list_databasesTeams, the role in each, owned and shared databases
list_namespaces · list_tablesOnly what the grants allow
describe_table · describe_viewSchema, partitioning, snapshots, branches, view SQL
list_semantic_models · describe_semantic_modelDatasets, joins, agreed metrics and AI context · a summary, searchable, for large models
query_semantic_modelAnswers from the agreed metrics and joins, read with the user's own grants
list_dimension_valuesExact filter values, such as Example Dunmore
preview_rowsUp to 100 rows, at any snapshot
list · create · update · delete_shareTeam administrators only · sharing a model adds its tables
create · rename · delete_databaseTeam administrators only · delete needs the exact name
  • The agent signs in through Keycloak as you: a public client with PKCE, no secret to store.
  • Every call runs with your Polaris grants, so the agent sees exactly what you see and nothing more.
  • The agent never writes SQL: it names metrics, dimensions and filters, and the portal builds the query from the semantic model, so a metric always uses the agreed definition.
  • A shared database stays read-only for the agent too.
  • Destructive tools are marked as such, and the agent is told to ask before using them.
02 · Platform · Extensions

Keep the core small: extensions come in through one Bridge

Conversational BI, an extension with a gateway, an agent and a query worker, talks to the core platform only through the Extension Bridge at /bridge/v1: the signed-in user's teams and databases, automation principals per team and environment, and one-hour catalog tokens. With that token its query worker reads tables and models over Iceberg REST and S3, like any other client. Secrets, storage keys, core source code, container names and the Polaris management API never cross. Extension · iceberg-conversationalbi Contract Core · iceberg-platform Conversational BIown release · :3007 Gatewaychat UI · REST API · MCP AgentPydantic AI, defined in YAML · any LLM Query workerDuckDB · one locked-down process per query Extension Bridge/bridge/v1 · contract 0.1.1 GET /meteams, roles, own and shared databases automation principalsone per team and environment, enabled by its admins POST …/tokensa one-hour catalog token, read only for this extension Core platformsmall, released on its own Keycloakthe extension's own ext-… clients Apache Polaristables and semantic models RustFSvended, table-scoped credentials user context with that token: Iceberg REST and S3, the open standards every client uses Never crosses secrets · storage keys · core source codecontainer names · the Polaris management API
02 · Platform · Extensions

Team administrators switch it on, the platform keeps oversight

Conversational BI model list for mila with grid-planning development and production not enabled yet, each with an Enable button Admin portal Teams page with the extension service accounts of Conversational BI for outage-response and grid-planning, each with Revoke
02 · Platform

Security model, in one slide

  • The user portal, Polaris, the notebooks and MCP all work with that user's Keycloak token. No shared service account for data access.
  • Polaris vends short lived, table scoped S3 credentials; notebooks never see bucket root keys.
  • Each notebook session gets its own container and network: read-only root filesystem, dropped capabilities, CPU, memory and process limits, no Docker socket.
  • Revoking a membership stops the affected runtimes within 30 seconds.
  • A data share holds one read grant per table, view or semantic model. A receiving team never gets administration; an external secret is shown once, never stored. A listing in the data catalog publishes metadata only.
  • MCP accepts only tokens issued to the iceberg-mcp client, verified on every call: an agent never holds more than its user.
  • Extensions get no platform secrets or storage keys: a team's service account, enabled by its administrators and revocable by the platform administrator. dbt and Ingestion runs are isolated containers with a short-lived token.
03

From raw data to answers

A load forecast written in a notebook, given meaning by its contract, shared, listed in a data catalog and asked about in a chat.

03 · Demo · Notebook

A notebook checks the data product, then writes it

Example notebook 09 in the grid-sensors database: a query joins the congestion outlook to assets, feeders and substations and counts future congestion points per substation, with the resulting table Example notebook 09: the contract's quality checks, run as SQL, all with zero violations, before the tables are written to Iceberg
03 · Demo · Semantic model

The meaning, stored beside the tables

Diagram tab of the mv_load_forecast semantic model: eight datasets drawn as tables with their keys, relationships as lines between the join columns
↓ AI context and metrics
User portal · semantic model overview with its AI context
User portal · the agreed metrics and relationships
03 · Demo · Data sharing

Share the model with another team, without a copy

User portal data share form with outage-response as recipient team, the mv_load_forecast semantic model selected and its eight tables added noor's catalog of the shared grid-sensors database, marked shared and read-only: eight tables and one semantic model, owner named
03 · Demo · Data catalog

List it in the data catalog, so others find it

User portal data share form for mv-load-forecast-catalog: only Listed in the data catalog checked, with grid-planning@example.com as the contact for access requests and the mv_load_forecast model selected OpenMetadata data product mv-load-forecast-catalog: the agreed metrics, the ER diagram of its eight tables with their primary and foreign keys, and the list of foreign keys
↓ a table and a metric up close
OpenMetadata · load_forecast with the model's descriptions, glossary terms and keys
OpenMetadata · the agreed congestion_points metric with its description and dimensions
03 · Demo · Conversational BI

noor asks the shared model a question

Conversational BI answer for noor on the shared mv_load_forecast model: a query card with congestion_points by SUBSTATION.name for offtake, the join path from congestion to substation, and a bar chart led by Example Dunmore with 38
↓ the SQL
Conversational BI · the SQL compiled from the model: the agreed metric and the joins from congestion to substation
03 · Demo · Conversational BI

How a question becomes a governed query

1 · The LLM picks namesanalyst.yaml · any providerMetrics, dimensions and filters from the selected model. It sees the model's context and at most 20 sample rows, never a credential.
2 · The model writes the SQLcompiled, not generatedThe agreed metric SQL, joined only along the model's relationships. An allowlist refuses subqueries, table functions and file readers.
3 · A disposable worker readsDuckDB · one process per queryWith the team's one-hour read token and vended, table-scoped credentials. Shared models need nothing extra: the team's read role reaches them.
4 · The answer shows its workCopilotKit · Chart.jsQuery card, definitions, join path and SQL. The chart loads its rows from the result by id, never from the LLM.
Wrap up

As far as I'm concerned

  • Iceberg complements platforms like Snowflake. Use it where openness pays off: data that several teams, engines or partners read. Not every table needs to be an Iceberg table.
  • Combining data products is where an integrated platform wins. Joining many data products in one place with good performance is easier when storage, compute and catalog come from one vendor.
  • For Iceberg tables, engines are replaceable. My advice is to treat them as workload decisions, not as platform commitments.
  • Meaning belongs next to the data. A semantic model is part of the data product: owned by the team, checked before it is published, and shared and governed like the tables.
  • Self-service only works with clear ownership. Teams create, own and share their databases, while the platform team owns the building blocks.
  • Agents use the same front door. They get the same identity and grants as the people they work for.
  • Keep the core small, grow through extensions. New capabilities such as Conversational BI, dbt pipelines, Ingestion and OpenMetadata come with their own release, behind one versioned contract.
Thanks

Reach out.

Want to run this yourself, or see a gap I missed? Let me know. We'll take it from there.

Regards, Sander
github.com/sanderdw/iceberg-data-platform
Apache-2.0