Postgres holds the live data; BigQuery is where the dashboards live. Data Sync connects them without a Fivetran subscription: pick a source table, pick a target, map the fields, and set a schedule.
No credit card. 14 days. Cancel in one click.
Quick answer: Add Postgres and BigQuery connections under Databases, then in Pipelines → Build, start a New Sync with Postgres as the source and BigQuery as the target. Map fields, pick Insert, Update, or Upsert, and Dry Run before saving it as a scheduled job. Pipelines tier, and note that Postgres syncs need QueryFlow's background helper support list (Snowflake, Redshift, BigQuery, Databricks) or the app open to run unattended.
A working Postgres connection and a working BigQuery connection, both added under Databases, and a BigQuery dataset that already exists (QueryFlow writes to tables inside it, it doesn't create datasets). Pipelines tier, since Data Sync is a Pipelines feature.
A SaaS company keeps its orders table in Postgres and wants a daily rollup in BigQuery for the team already building dashboards there. The source query, run against Postgres:
SELECT order_date, customer_id, status, total_cents, updated_at FROM public.orders WHERE updated_at >= now() - interval '2 days';
The BigQuery target table, referenced the way BigQuery expects it, with the project and dataset spelled out and backticked because BigQuery table paths contain hyphens that break unquoted identifiers:
`my-gcp-project.analytics.orders_rollup`
Map order_date, customer_id, status, and total_cents to the matching BigQuery columns, pick Upsert, and set MATCH ON to a composite of order_date and customer_id (or just the order's primary key if you're syncing whole orders rather than a rollup). Under the hood this becomes a BigQuery MERGE, which is how QueryFlow implements Upsert against BigQuery targets: matched rows get updated, unmatched rows get inserted, in one statement rather than a separate delete-then-insert.
Run Dry Run first and confirm the row count looks right before committing to a live schedule. After a real run, query the BigQuery table directly and spot-check a handful of rows against the Postgres source, and check the run history in the Observatory for anything that failed silently on a type mismatch.
| If you see | Fix |
|---|---|
| No BigQuery connections available | Add one under Databases first, with a service account that has BigQuery Data Editor if you're writing new rows. |
| Job fails on write | Check the service account or Google account has BigQuery Data Editor on the target dataset, not just Job User and Data Viewer. |
| Duplicate key values in source for key column(s) … | Your MATCH ON column, or combination, isn't unique per row in the Postgres query. Narrow the query or add a column to the match. |
A managed Postgres-to-BigQuery connector from Fivetran or Airbyte buys you continuous log-based replication and a hosted pipeline you don't have to keep running. QueryFlow buys you a flat price and a pipeline you can see and edit directly, at the cost of running on a schedule rather than streaming, and needing your Mac (or a Mac left on as a server) available for the sync to fire, since Postgres syncs aren't in the list of jobs the background helper runs with QueryFlow fully closed — that list is Snowflake, Redshift, BigQuery and Databricks jobs only. If a five-minute or hourly cadence is fine for the destination table, that tradeoff is usually a non-issue; if you need true log-based CDC with sub-minute freshness and zero tolerance for the Mac being asleep, that's a real reason to stay on a managed connector.
Fivetran prices connectors by Monthly Active Rows (MAR): distinct primary keys that see an insert, update, or delete in a calendar month, counted once no matter how many times that same row changes again that month. Fivetran's own pricing page lists a $5 base charge per standard connection plus per-MAR usage, with the free plan covering 500,000 MAR before any charge applies. A single Postgres orders table with a few hundred thousand actively-changing rows a month can sit inside the free tier or land in Fivetran's lower usage bands; a busier one with several million MAR moves into paid usage that scales with row activity, not with anything QueryFlow charges for. QueryFlow's Pipelines tier is $29.99/month or $199.99/year flat, with no per-row metering at all — the price doesn't change whether the orders table has ten thousand rows or ten million, only how long the sync takes to run.
If a column gets added to the Postgres orders table after the sync is built, QueryFlow doesn't silently pick it up and add it to the BigQuery target. The field mapping stays as drawn until you open the sync and add the new field yourself. That's a deliberate tradeoff: a mapping you can see and edit, rather than an automatic schema-drift handler that occasionally reshapes a production table without asking.
| Postgres type | BigQuery type | Note |
|---|---|---|
| INTEGER / BIGINT | INT64 | Direct mapping, no precision loss. |
| NUMERIC(p,s) | NUMERIC or BIGNUMERIC | Use BIGNUMERIC if precision exceeds BigQuery's NUMERIC range (38 digits). |
| TIMESTAMP WITH TIME ZONE | TIMESTAMP | BigQuery's TIMESTAMP is always UTC internally; confirm the source column's zone before mapping. |
| JSONB | JSON or STRING | Native JSON type preserves structure; STRING is safer if you plan to parse it downstream yourself. |
| BOOLEAN | BOOL | Direct mapping. |
| TEXT / VARCHAR | STRING | No length limit concerns on the BigQuery side. |
Get the type mapping wrong on a first run and the failure is usually loud, a rejected write with a clear type-mismatch error, rather than silent corruption, since BigQuery enforces column types on load rather than coercing loosely.
Postgres NULL values come through as BigQuery NULL without extra configuration, which matters for the MATCH ON column specifically: a null value in a MATCH ON field won't reliably match itself across runs the way you'd expect from equality logic, so avoid using a nullable column as your key. For a Postgres table in the tens of millions of rows, the first full sync (before any incremental filter narrows it) can take a while depending on both Postgres read throughput and BigQuery's load API; narrowing the initial run with a date range and backfilling in chunks is usually faster and easier to monitor than one enormous first pass.
Once a sync is scheduled, the Observatory dashboard shows every run's duration, row count, and outcome, which is worth checking periodically even after the sync has been reliable for months, since a source schema change or a permissions rotation on the BigQuery side can cause a run to start failing without anyone noticing until a downstream dashboard looks stale. A quick habit worth building: after any change to the Postgres orders table's columns, or any BigQuery service account credential rotation, re-run Dry Run once before trusting the next scheduled run.
If a scheduled run fails partway through, for example a transient network blip between your Mac and BigQuery, QueryFlow surfaces the failure in the run history with the underlying error rather than silently marking it successful, and a retry re-runs the same source query fresh rather than trying to resume mid-write, so a failed run is safe to simply retry once whatever caused it (a dropped connection, an expired token) is fixed.
See also: Integrations Load a CSV into BigQuery on Mac Sync Databricks to BigQuery.
No. Add a column in Postgres and it won't appear in the BigQuery target until you edit the field mapping yourself and re-save the sync.
Yes. Build a separate sync for each table, each with its own mode and MATCH ON, and schedule them independently or as one job list.
QueryFlow reads whatever is committed at query time. An in-flight transaction that hasn't committed yet simply isn't visible to that run and will be picked up on the next one.
Either works. A personal Google sign-in is fine for one person's own use; a service account key is the better choice for a shared or scheduled pipeline so it doesn't depend on your login session.
A one-time export gets you a snapshot. This is a saved, schedulable sync that re-runs Insert, Update, or Upsert logic every time, so the BigQuery table stays current without anyone repeating the export by hand.
14-day free trial, no card. Build the sync, Dry Run it, and see the rows land.
No credit card. 14 days. Cancel in one click.