Supabase just shipped Pipelines: near real-time replication from your Postgres into BigQuery and other analytical destinations, powered by an open-source Rust engine. Read the engineering write-up from the team and one word runs through all of it. Faithful. Every change moves with no silent loss. At-least-once delivery. Persistent replication state. And the headline alpha feature, schema evolution: when a column changes at the source, Pipelines detects the change and applies it to the destination for you.
That faithfulness is the whole point. It is also the risk nobody is talking about yet.
Faithful replication is only as good as the source it is faithful to.
Pipelines treats your Postgres as authoritative and replicates it exactly. Its hard problem is surviving infrastructure failure, not deciding whether the source data is correct. So when your tracking breaks in a pull request, Pipelines does not stop it. It carries the break all the way to the warehouse, schema change and all, and every hop stays green while it does.
Here is what that looks like. Flip the toggle.
Pipelines replicated the rename faithfully. checkout_completed stopped, the funnel went flat, and every hop stayed green.
Key takeaways
- Supabase Pipelines guarantees the pipe: it moves your data faithfully, carries schema changes, and does not silently drop rows. It does not, and is not meant to, decide whether the events at the source are correct or complete.
- Schema evolution means a broken event rename now propagates all the way to BigQuery on its own, so the break is no longer contained in your app database. It fans out to every downstream table, query, and model.
- The most dangerous breaks look healthy. Volume is fine, the pipeline dashboard is green, and a funnel quietly goes flat or loses a dimension from the merge date.
- Skene sits one step before Postgres, on the pull request. It catches the four ways tracking breaks and the fifth that only intent can catch: the event that was never added at all.
- Together they fit with no overlap. Skene keeps the source authoritative, which is the one assumption Pipelines is built on and does not check itself.
Pipelines guarantees the pipe. Skene guarantees what goes into it.
The two products never touch the same job. Pipelines lives after Postgres, moving rows to the warehouse with strong delivery guarantees. Skene lives before Postgres, on the pull request, checking that the events being written are complete and correct in the first place.
code (PR) -> Postgres (events) -> Pipelines (CDC + schema) -> BigQuery -> dashboards
^ ^ ^
Skene checks here Pipelines guarantees this hop everyone trusts this
(is the event right?) (no loss, schema carried) (only as good as arrow 1)
Faithful replication makes the first arrow matter more, not less. If the event is wrong when it enters Postgres, Pipelines will make sure the wrongness arrives everywhere, on time, intact.
Four ways a green pull request poisons your warehouse
The setup is the same for all four. A product-led SaaS on Supabase turns on Pipelines to replicate its events table into BigQuery, so the growth team can run funnels off the warehouse without loading production. Initial sync ran. CDC is live. Everyone has stopped double-checking.
Now watch four ordinary pull requests.
1. The rename Pipelines carries downstream
A coding agent tidies the checkout module and renames the event.
// checkout.ts
- track("checkout_completed", { plan, amount })
+ track("purchase_completed", { plan, amount })
Green build. Merged. Postgres stops receiving checkout_completed. Pipelines replicates the new rows faithfully, so BigQuery now has purchase_completed and zero new checkout_completed. The activation funnel filters on the old name. It does not error. It goes flat from the merge date, and the pipeline health dashboard stays green.
The column-rename version is worse. alter table events rename column plan_tier to tier is a DDL change, so Pipelines detects it and applies it to BigQuery automatically. Every scheduled query that reads plan_tier breaks or silently reads null. Pipelines did exactly what it promised. The break was upstream, in intent, and schema evolution amplified it across the warehouse.
Skene flags on the PR that checkout_completed was removed, names the file and line, and offers /skene fix to restore it or propagate the rename on purpose, everywhere it needs to go.
2. The dropped field that goes null all the way
A cleanup drops a property that "nobody uses."
// signup.ts
- track("signup", { source, plan })
+ track("signup", { source })
Volume looks perfect, so nothing trips. But plan is null from the merge date, and Pipelines carries the nulls across without complaint. "Signups by plan" quietly loses its dimension. The person who reads that chart is not in the pull request.
Skene flags the dropped plan property and the breakdown that depends on it.
3. The event that never existed, so there is nothing to replicate
An agent ships a new share-to-Slack flow. It works. It has no tracking.
// share.ts
await postToSlack(channel, summary)
+ // TODO: analytics (never written)
Pipelines does nothing here, correctly. There is no event to move, so BigQuery has no such rows and never will. A month later the question "how many shares, and do sharers retain better?" has no answer and cannot be backfilled. This is the gap Pipelines structurally cannot see. It moves what exists. It cannot tell you what should exist and does not.
Skene flags, on the PR that added the feature, a new user-meaningful action shipped with no tracking, and proposes the capture with the properties the funnel will need.
4. The firing condition that quietly narrows
A refactor moves a capture inside a branch.
// feature.ts
- track("feature_used", { feature })
+ if (user.plan !== "free") {
+ track("feature_used", { feature })
+ }
The event still exists in BigQuery, so nothing looks broken at all. But it is now missing every free-tier user. Free-tier engagement and retention silently skew upward, because the users who churn are the ones no longer counted. The most dangerous break, because the number only moves a little.
Skene flags that feature_used moved into a branch that excludes free-tier users, so its firing surface changed.
The same discipline, one layer up
The team did not make Pipelines correct by hoping. They encoded invariants in the type system, added assertions such as a debug check that replication progress never moves backward, and wrote fault-injection tests that fail after a destination write but before acknowledgement. That is correctness discipline for the pipe.
Skene is that same discipline for the application's event layer. Every event is an invariant about the product: this action must be captured, with these properties, on this path. Skene checks those invariants on every pull request, the way Pipelines checks its ordering invariant on every change. It is what keeps the source authoritative, which is the assumption Pipelines depends on and does not verify itself.
Why this matters now
Two waves are arriving together. Teams are turning on Pipelines and starting to trust the warehouse. The same teams are shipping with coding agents that rewrite the code that writes the events, with no model of why an event exists. Before Pipelines, a broken rename stayed in your app database until someone noticed. After Pipelines, it fans out to every table and model reading BigQuery, on schedule, looking healthy.
Skene is the check that keeps the source honest, so Pipelines' faithfulness is an asset and not an amplifier. It reads your repo and your Supabase, read-only, and comments on the pull request the moment a write breaks, while the data is still recoverable.
Run npx skene audit to see what is already broken in your repo. No signup. Then wire it into your pull requests, turn on Pipelines, and let both do the one job each is good at.
Continue with Skene
How Skene works
Skene reads the event writes in your code and checks them against your Supabase schema on every PR.
Skene vs. analytics tools
Compare keeping your telemetry in your own Supabase to shipping events to hosted product analytics platforms.
Pricing
Open-source core is free. Paid plans start at $29/month with a 1.5M token budget.
