"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.
  • COPY query 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_tables view 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. VACUUM merges 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