"Postgres Iceberg" covers four different jobs. You might want to query Iceberg or Parquet files on S3 from Postgres. You might want Postgres to write Iceberg tables. You might want Postgres to be the catalog that other engines use. Or you might want your Postgres data to land in Iceberg for a warehouse to read. Each job has a different tool, and two of the tools people still recommend are no longer maintained.
This post sorts them out. I have not run pg_lake or Iceberg in production. What I did run, on my laptop: PyIceberg 0.12.0 with a plain Postgres 16 container as the Iceberg catalog, and the pg_duckdb Docker image (Postgres 18.1) reading the same table. The numbers below come from those runs. Everything else links to its source, checked on 1 October 2026.
Postgres and Iceberg: the options at a glance
| Option | Job | Licence | Latest release | Status |
|---|---|---|---|---|
| pg_lake | Write and read Iceberg, Postgres as catalog, COPY to/from S3 | Apache-2.0 | v3.5.3, 2026-09-24 | Active |
| pg_duckdb | Read Parquet, CSV, JSON, Iceberg, Delta; fast analytics | MIT | v1.1.1, 2025-12-18 | Active, PG 14 to 18 |
| PyIceberg / Iceberg JDBC SQL catalog | Plain Postgres as the catalog only | Apache-2.0 | PyIceberg 0.12.0 | Active |
| Snowflake Postgres | Managed Postgres with pg_lake | Commercial | GA 2026-02-24 | Active |
| Supabase Analytics Buckets + Supabase ETL | CDC from Postgres into Iceberg on S3 Tables | ETL is Apache-2.0 | — | Public alpha |
| Databricks Lakebase | Managed Postgres, sync to the lakehouse | Commercial | GA on AWS 2026-02-03 | Sync is beta, Delta only |
| pg_mooncake | "Real-time analytics on Postgres tables" | MIT | v0.1.3 | Dormant: team joined Databricks |
| ParadeDB pg_analytics | DuckDB-backed lake queries | PostgreSQL | — | Archived 2025-03-19 |
The short version: pg_lake if Postgres should own Iceberg tables, pg_duckdb if Postgres only needs to read the lake, and a managed product if you want someone else to run the plumbing.
pg_lake: Postgres that writes Iceberg
pg_lake began as Crunchy Data Warehouse. Snowflake bought Crunchy Data in June 2025 and open-sourced the code as pg_lake in November 2025. Per its README, it lets you:
- Create and change Iceberg tables from Postgres, inside ordinary transactions.
- Query Parquet, CSV, JSON and Iceberg files in object storage.
-
COPYquery results out to S3 as Parquet, CSV or JSON, and back in.
CREATE EXTENSION pg_lake CASCADE; CREATE TABLE events (id bigint, ts timestamptz, kind text) USING iceberg; INSERT INTO events VALUES (1, now(), 'view'); COPY (SELECT * FROM events) TO 's3://bucket/exports/events.parquet'; The design has two parts. Postgres runs the pg_lake extensions. A separate process, pgduck_server, runs DuckDB and speaks the Postgres wire protocol locally. pg_lake hands scans and computation to it. You don't query it directly, but you do deploy and size it: it defaults to 80% of system memory, per the README.
From the Iceberg tables doc:
- Postgres is the catalog. Commits update pg_lake's catalog tables in the same transaction as the data change. An
iceberg_tablesview lets Spark, PyIceberg and iceberg-rust find the tables through their JDBC or SQL catalogs. - REST catalogs work too. A table can live in an external REST catalog, so other engines see it where they already look.
- Compaction is built in.
VACUUMmerges small files and removes expired ones, and autovacuum runs it every 10 minutes. - Some SQL is not supported on Iceberg tables:
MERGE,INSERT ... ON CONFLICT,SELECT ... FOR UPDATE. An update or delete locks the table, so only one runs at a time. - Other engines read, Postgres writes. External tools cannot yet write to tables pg_lake created. Tables attached from a REST catalog are read-only in pg_lake.
The managed form is Snowflake Postgres, generally available since 24 February 2026. Since 14 July 2026 a catalog integration lets Snowflake discover those tables and read them as read-only Iceberg tables.
I did not run pg_lake for this post. Its Docker setup builds the images locally rather than pulling a ready one, and I chose to test the parts I could run honestly in an afternoon.
This is the first part. The full post — including the rest of the working details — is on my site: Postgres and Iceberg: pg_lake, pg_duckdb and the Postgres lakehouse