How to sync Postgres views
A quick tutorial on how to sync a Postgres (or Supabase) view with Whalesync
Whalesync can't modify Postgres views safely, so it won't create its usual primary key column on a view the way it does for regular tables. Views still need a unique column for tracking each record — you add it yourself, and this page shows how.
What Whalesync looks for
A column on the view itself named exactly whalesync_postgres_id (all lowercase). That's the only thing Whalesync checks for — it doesn't matter whether the column comes from the underlying table, an alias, or an expression.
Once the column exists, click Refresh tables in Whalesync and the view is ready to sync.
What the column's values must satisfy
Whalesync uses this column as the ID of each record, so its values must be:
Unique — no two rows of the view ever share a value.
Non-null — every row has a value.
Stable — a row keeps the same value for its whole life. The value must never change when the row is updated.
Any column type works (uuid, integer, bigint, text, …) as long as the values meet those three rules. Whalesync does not validate them up front: duplicates, nulls, or changing values will cause records to be skipped, merged together, or treated as deleted and re-created during sync.
Option 1: expose an existing column (no changes to the underlying table)
If the underlying table already has a compatible column — typically its primary key — you don't have to modify the table at all. Append it to the view's select list under the required name:
CREATE OR REPLACE VIEW public.my_view AS
SELECT
t.name,
t.created_at,
t.id AS whalesync_postgres_id -- existing unique, non-null, stable column
FROM public.my_table t;Note: CREATE OR REPLACE VIEW can only append new columns at the end of the view's column list — it can't rename or reorder existing output columns. Adding t.id AS whalesync_postgres_id as a new last column works even if the view already exposes t.id under another name. If you need to restructure the view instead, DROP VIEW and recreate it (watch out for dependent objects).
Views over joins or aggregates
If the view joins tables or groups rows so that no single base-table column is unique per view row, build a stable composite value from the keys that define each row:
This is unique and stable as long as the combined keys are.
Option 2: add a new column to the underlying table
If no existing column qualifies, add the same column Whalesync would create on a regular table, then include it in the view:
Let an AI assistant write the query for you
Copy the prompt below into Claude Code (or another AI assistant), paste in the SQL for your view and the tables it reads from (see Getting the SQL to paste), then run the SQL it returns in the Supabase SQL editor or your Postgres client.
Getting the SQL to paste
The assistant needs two things: the definition of the view and the definitions of the tables it reads from — including their names, so it can write SQL you can run as-is.
The easiest way is to copy the full SQL from your database tool:
Supabase: go to Database → Tables, open the "…" menu on the view and on each table it reads from, and choose Copy table schema. Paste everything into the prompt.
Other tools (TablePlus, DBeaver, DataGrip, pgAdmin, …): open the view and each underlying table and copy the SQL from the Schema or DDL tab.
If your tool doesn't offer that, run this query instead after replacing every public.my_view with the name of your view.
Paste both into the prompt, along with a description of each underlying table — at minimum its name, its columns, and which column is the primary key.
After adding the column
Go back to Whalesync and click Refresh tables. The view will drop out of the "needs setup" state and can be mapped and synced like any other table.
Video Tutorial
This video tutorial is a little out of date and may not match the current UI. It also only covers the approach of adding a column to the underlying table.
Last updated
Was this helpful?

