Lakebase change data feed, from Postgres into Delta
kept in this browser
Edit this pageEvery insert, update and delete in a Lakebase schema recorded as rows of a Unity Catalog Delta table, read from the Postgres write-ahead log.
On the preview radar: Lakebase change data feed
On this page8
What it is
The Lakebase change data feed records the changes made to Postgres tables in a Lakebase database as rows in Unity Catalog managed Delta tables. For a Postgres table orders, every insert, update and delete arrives in a history table named lb_orders_history, with columns saying what kind of change it was and where it sits in the transaction log.
It is the opposite direction of a synced table: synced tables bring lakehouse data into Postgres, the change data feed brings Postgres changes into the lakehouse. It is in Public Preview since May 2026, and a workspace admin has to enable it on the Previews page. A March 2026 release note announced it under the name Lakehouse Sync.
Why it exists
Operational data is where the facts start: orders placed, accounts changed, tickets closed. The lakehouse needs them for reporting, features and models, and the classic route is a CDC tool reading the database’s replication log into a message bus, then a pipeline landing the events in tables — three systems, three sets of credentials, and a replication slot on the production database that someone has to watch.
Lakebase does not offer native logical replication to external tools. What it offers instead is that route built in: the platform reads the log and writes Delta, governed by Unity Catalog from the first row.
How it works
Reading the log
A Postgres extension, wal2delta, reads the write-ahead log and turns each change into a row. Changes are written to Delta in batches, roughly every 15 seconds. Each row carries the table’s columns plus:
| Column | Meaning |
|---|---|
_pg_change_type | insert, delete, update_preimage or update_postimage |
_pg_lsn | Position of the change in the write-ahead log |
_pg_xid | The Postgres transaction ID |
_timestamp | When the change happened |
_sort_by | A value to order changes deterministically |
An update produces two rows, the row before and the row after, the same pre-image/post-image shape as Delta’s own Change Data Feed. The history table is an append-only log of changes, not a mirror of the current state: the current state is derived from it downstream.
Setting it up
- Each source table needs a full replica identity, so that updates and deletes carry the whole old row:
ALTER TABLE shop.orders REPLICA IDENTITY FULL;
- On the branch, in the Lakebase CDF tab of the Lakebase app, start a feed for a schema and choose the destination catalog and schema in Unity Catalog. Every table in the Postgres schema, today’s and future ones, is included.
A feed reads one source database. The person setting it up needs CAN MANAGE on the project, and USE CATALOG, USE SCHEMA and CREATE TABLE on the destination. The source runs Postgres 16, 17 or 18.
Limits
- Partitioned tables and empty tables are skipped.
- A schema change on a source table triggers a full re-snapshot of that table into its history.
- The destination cannot be a catalog on default storage, nor storage reachable only through a private endpoint.
- Types with no Delta equivalent — PostGIS geometries, pgvector vectors, composite types,
hstore— arrive asSTRING. - Adding row filters or column masks to a destination table, or enabling Delta’s change data feed on it, breaks the feed. Apply those on the tables you derive from it.
Before this feature, Provisioned Lakebase had a private preview called Forward ETL; it is no longer supported.
Example
Turning the history into a current-state silver table, one row per order, latest change wins:
CREATE OR REPLACE TABLE main.silver.orders AS
SELECT * EXCEPT (_pg_change_type, _pg_lsn, _pg_xid, _timestamp, _sort_by, rn)
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY _sort_by DESC) AS rn
FROM main.bronze.lb_orders_history
WHERE _pg_change_type <> 'update_preimage'
)
WHERE rn = 1
AND _pg_change_type <> 'delete';
The history table is the bronze layer here; the silver table is rebuilt, or maintained incrementally with an AUTO CDC flow, from it (see Medallion architecture: bronze, silver, gold). Analysts query silver; the application never notices.
Common mistakes
- Forgetting
REPLICA IDENTITY FULL. Without it updates and deletes do not carry the old row, and the history is incomplete. - Querying the history as if it were the table. It holds every version of every row. Derive the current state.
- Partitioned source tables. They are skipped silently; the missing table is noticed later, downstream.
- Securing the history table in place. Row filters, column masks and Delta CDF on the destination stop the feed. Secure the derived tables.
- Relying on it for a production pipeline as if it were GA. It is Public Preview: supported, and still able to change.