Comparisons / Migration frameworks
RowShield vs node-pg-migrate: JavaScript migrations versus monitoring
The short version
- node-pg-migrate is a Node.js migration framework over node-postgres: migrations defined programmatically in JavaScript, run by CLI or library. RowShield is a scheduled Supabase monitor that checks what those migrations never express — row level security, storage exposure, key leakage — and probes what the anon key can actually read.
- Choose node-pg-migrate when — a Node team wants migrations as code, with programmatic control over every statement.
- Choose RowShield when — your Express or Next.js backend sits on Supabase and you want scheduled proof that policies, buckets and keys stayed safe between deploys.
RowShield rules relevant here
Head to head: node-pg-migrate vs RowShield
| Capability | node-pg-migrate | RowShield | Edge |
|---|---|---|---|
| Defining change | JavaScript APIs construct tables, columns and indexes; raw SQL available when needed. | No migration authoring; scans observe the result whatever authored it. | node-pg-migrate |
| Authorisation vocabulary | Policies fall to raw sql() calls; the framework executes them without evaluation. | Policies are the monitored dataset: existence, conditions and write coverage checked semantically. | RowShield |
| Dangerous-pattern detection | Syntactically valid SQL succeeds regardless of meaning. | RLS_TAUTOLOGY, RLS_NO_POLICIES, RLS_DISABLED and MISSING_WITH_CHECK flagged per table and role. | RowShield |
| Public-surface testing | Not applicable; nothing addresses the HTTP layer. | GET-only probe requests PostgREST as the anon role and reports readable tables per scan. | RowShield |
| Between-deploy observation | Runs only when someone invokes it, then goes quiet between releases. | Scheduled scans up to every fifteen minutes; dashboard and AI-applied edits caught between runs. | RowShield |
| Alerting and memory | Console output and exit codes at run time. | Snapshot diffs classified created/resolved/regressed; alerts to Slack, Discord, email and webhooks. | RowShield |
| Node ergonomics | Natural fit for JS codebases; migrations live beside the code. | Stack-neutral external monitor. | node-pg-migrate |
Column claims about node-pg-migrate are sourced below. Where the edge is theirs, the page says so — and the sections that follow explain why Supabase teams still pick RowShield.
What node-pg-migrate does
node-pg-migrate, maintained by Salsita and documented in its README reviewed 2026-08-23, lets Node.js teams define migrations programmatically: functions receive helpers for creating tables, columns and indexes, run by CLI against a connection string or embedded in an application. Raw SQL is available throughout for anything the helpers omit.
That last clause carries the story. On Supabase, the important statements are precisely the ones helpers do not model — CREATE POLICY and its conditions, bucket configuration, grant adjustments — so the authorisation layer of a node-pg-migrate codebase typically consists of opaque strings executed faithfully and never revisited.
Where the scopes differ
Programmatic migrations buy determinism for structure; authorisation remains stringly typed and unaudited. A sql() call containing USING (true) runs exactly like a correct predicate, and a migration rebuilding a table can shed its policies without the framework noticing anything amiss, because noticing requires interpreting policy text — outside the tool’s remit.
RowShield takes that remit deliberately. Scheduled scans read the live catalog and interpret the authorisation objects: constant-true conditions, absent WITH CHECK clauses, disabled RLS, missing coverage — each with severity, each tied to a shipped rule. Storage and key exposure rules extend coverage past the database proper, where Supabase keeps half its risk.
The probe then settles behaviour empirically: GET requests to PostgREST as the anonymous visitor, recording which tables return rows. Between deploys — where dashboards and AI assistants make unversioned edits — scheduled scans keep watch, and the accumulated snapshot history labels any returning problem a regression rather than letting it pose as news.
Why Supabase teams choose RowShield over node-pg-migrate
JS teams adopt node-pg-migrate for control and keep it; RowShield joins for the assurance layer the control never provided. Setup is minutes — URL alone powers the free probe; a read-only connection string adds scheduled monitoring on a paid plan with hourly or quarter-hourly frequency by plan.
The nine-rule catalogue speaks Supabase natively, down to SERVICE_ROLE_KEY_EXPOSED scanning deployed frontend bundles for leaked privileged keys. Findings arrive with remediation SQL generated from your columns, FORCE ROW LEVEL SECURITY included, and the CLI offers identical checks with CI-safe exit codes beside your npm run migrate step.
Where node-pg-migrate is the right choice
For Node codebases wanting migrations as reviewable code, node-pg-migrate is a solid choice with a straightforward API and no framework lock-in, and we recommend it for that role without reservation.
Small projects whose schemas rarely move may reasonably defer monitoring altogether; the calculus changes the day strangers can reach the API.
Using both
Write migrations as before; let scheduled scans certify what they left behind — policies interpreted, buckets checked, anon surface probed. Authoring and auditing, split cleanly.
RowShield reads pg_catalog metadata only and is built by Veristria, unaffiliated with Salsita or the node-pg-migrate maintainers; the project is referenced descriptively as open-source software.
Frequently asked
- Is RowShield affiliated with node-pg-migrate or Salsita?
- No. RowShield is built by Veristria, an independent company, and is neither endorsed by nor affiliated with Salsita or the maintainers of node-pg-migrate, which is referenced descriptively as an open-source project.
- Is RowShield a good node-pg-migrate alternative?
- For authoring JavaScript-defined Postgres migrations, no — node-pg-migrate serves that well and should keep the job. For continuously verifying Supabase authorisation posture and behaviour, yes: RowShield monitors the layer raw sql() calls leave unexamined.
- What does ANON_TABLE_READABLE actually mean in a finding?
- That the probe’s GET request as the anonymous role received rows from that table. It converts policy inspection into observed behaviour — the direct evidence that a tautological or missing policy is reachable through the public API.
Check your project in about ten seconds
Paste a URL. No signup, no writes, nothing stored.
Run the free audit