Back
Safe / Not Safe Checks Postgres Migrations Before They Run
SiTech AI Team3 წთ. საკითხავი

Safe / Not Safe Checks Postgres Migrations Before They Run

A local-first open-source tool parses a Postgres migration in the browser with libpg_query and returns a SAFE, NOT SAFE or NEEDS CONTEXT verdict before the change reaches production.

A verdict before deploy

Safe / Not Safe (safenotsafe.dev) is a checker for PostgreSQL migrations that runs entirely in the browser. A developer pastes the migration into the editor, the SQL is parsed in a Web Worker by the libpg_query parser compiled to WebAssembly, and the tool returns one of three verdicts: SAFE, NOT SAFE or NEEDS CONTEXT. The goal, according to the project's README, is deliberately narrow: catch the familiar traps of schema changes before they reach production.

Before judging, the app asks two context questions: how many rows the target table holds (under 50k, 50k to 5M, over 5M) and whether the deploy tool wraps DDL in a transaction. That is why the third verdict exists: some statements are risky only at a certain table size or inside a transaction block.

What the rule catalog looks for

The rules are written in TypeScript, and the repository lists twelve checks: plain CREATE INDEX against CREATE INDEX CONCURRENTLY, CONCURRENTLY inside a transaction wrapper, added columns with literal or expression defaults, table rewrites caused by ALTER COLUMN TYPE, foreign keys added without NOT VALID, VALIDATE CONSTRAINT, SET NOT NULL, DROP COLUMN, renames, direct unique constraint builds, TRUNCATE, and rewrite commands such as VACUUM FULL and CLUSTER.

Each of them has a real cost. A plain CREATE INDEX blocks writes for the whole duration of the build; CREATE INDEX CONCURRENTLY avoids that but cannot run inside a transaction block. A column added with a constant default is cheap on modern PostgreSQL, but an expression or volatile default still rewrites the entire table. ALTER COLUMN TYPE usually rewrites the table and holds a strong lock while it does so. A foreign key added without NOT VALID validates every existing row immediately; adding it as NOT VALID and running VALIDATE CONSTRAINT later splits the work into two steps. Renames and DROP COLUMN are dangerous in a different way: during a rolling deploy, application instances that are still running query the old name.

Local work, and a CLI

The whole analysis happens inside the browser tab. Buffers are not written to disk, nothing is uploaded, and according to the project's privacy section there is no API route that receives pasted SQL, no database bindings and no telemetry. The same engine ships as a CLI: npx safe-not-safe check migration.sql prints the parse result in the terminal.

The stack is a React app shell built with Vite; the parser runs in an eagerly initialized Web Worker so the interface does not stall while the WASM parser compiles. The production target is Cloudflare Workers, whose configuration intentionally carries no D1, R2 or KV bindings. The source is open on GitHub in the viggy28/safe-not-safe repository.

SSiTech

SiTech — AI-powered web development

We build fast, modern websites and bring AI into real business workflows. Have a project or a question? We'd love to help.