MERGE per table applies inserts,
updates, and deletes by primary key. Each run catches up to the current WAL
position and stops, so you schedule runs as often as you need fresh data.
The PostgreSQL source is beta and
the BigQuery sink is alpha.
Prerequisites
- PostgreSQL with
wal_level=logicaland a primary key on every replicated table - A Google Cloud project with the BigQuery API and the BigQuery Storage API
(
bigquerystorage.googleapis.com) enabled - A Filament deployment backed by the PostgreSQL datastore, with the CLI pointed at it. The local SQLite CLI context cannot run CDC. See the note in Replicate PostgreSQL to Snowflake.
1. Prepare PostgreSQL
Enable logical replication, create a replication user, and create the publication as a table owner. These steps are identical to step 1 of the PostgreSQL to Snowflake guide:2. Give Filament access to BigQuery
The BigQuery sink authenticates with Application Default Credentials, so the connection has no credential fields. Credentials belong to the process that runs Filament’s workers. Create a service account and grant it the two roles the sink needs:dataEditor at the project level lets Filament create the destination dataset.
If you create the dataset yourself, you can grant dataEditor on that dataset
only.
Then make the credentials available to the workers:
- GKE: bind the worker’s Kubernetes service account to
filament@with Workload Identity. - Other platforms: mount a service account key and set
GOOGLE_APPLICATION_CREDENTIALSon the worker. - A laptop: run
gcloud auth application-default loginbefore starting Filament.
3. Create the source and sink
--sink-location applies when Filament creates the dataset. After that, the
dataset’s own location wins.
4. Create the pipeline and run the snapshot
shop.
5. Catch up on changes
Make changes in PostgreSQL:MERGE folds repeated changes to the same key into its
final state.
6. Verify
numeric(12,2) becomes
NUMERIC(12, 2), timestamptz becomes TIMESTAMP, and jsonb becomes JSON.
The full table is on the BigQuery sink
page.
7. Schedule it
Add a cron schedule in the web app or with the Pipelines API. Each run issues oneMERGE per changed table, so a 5 to 15 minute schedule keeps query costs
predictable.
Without CDC
If you cannot enable logical replication, use an incremental pipeline from a standard source, one created without--source-replication cdc. It needs a NOT NULL timestamp cursor such as
updated_at and does not capture hard deletes:
Troubleshooting
credentials: could not find default credentials
The worker process has no Application Default Credentials. Set up Workload
Identity, GOOGLE_APPLICATION_CREDENTIALS, or
gcloud auth application-default login as in step 2, then restart the worker.
Permission denied on bigquery.tables.updateData
The service account is missing roles/bigquery.dataEditor on the project or
the destination dataset.
create publication "filament": ERROR: permission denied
Create the publication as a table owner and set
--source-manage-publication=false.
CDC connections do not accept a read mode
Add --sync-mode cdc to filament pipeline create.
More errors are in Troubleshooting.
FAQ
Does Filament use the BigQuery Storage Write API?
Yes. Rows stream as Arrow over gRPC into staging tables, then a query publishes each table at commit.Does it replicate deletes?
Yes, with CDC andmerge. Incremental pipelines cannot see hard deletes.
Does Filament add primary key constraints in BigQuery?
No. Filament uses the primary key columns forMERGE conditions without adding
BigQuery key constraints.