The migration passed review.
It still took down production.
Bolvrk catches dangerous Postgres, SQLite and SurrealDB changes and committed secrets before they ship, whoever or whatever wrote them. Deterministic, no model in the verdict, ever. The CLI is open source; the full corpus runs in the cloud.
npx bolvrk check migration.sqlFree for individuals and open source. Teams pay flat per team, never per seat, and start without a sales call.
A PR opens. Rules judge it. The findings land in review.
migrations/0042_orders_region.sqlALTER TABLE orders
ADD COLUMN region text NOT NULL;
CREATE INDEX idx_orders_region
ON orders (region);The change is fast. The queue behind it isn't.
A lock that takes milliseconds still parks every write behind it, and on a hot table the backlog is the outage. That's why Bolvrk reads your real schema's shape and traffic: the same ALTER is harmless on a quiet table and a production incident on a busy one, and a checker that can't tell the difference is just noise.
AI writes more of your change stream every quarter
More of the change stream is written by AI now; review capacity hasn't kept up. Verification is the missing layer: judge the change, not the author. Your model proposes, our deterministic checker decides, and no AI is ever part of the verdict. Database changes and committed credentials are covered today; more surfaces are on the way.
Three layers of defense
Check locally
npx bolvrk check, the open-source CLI, runs the free outage rules over the database's real parse tree before the change ever leaves your machine.Gate every pull request
The GitHub Action checks changed migrations and comments the findings where review happens, free rules on the Free plan, the full corpus on Startup and above. Connect a database and it checks against your live schema: table sizes, foreign keys, column types.
Put it inside the agent
Add
bolvrk mcpto Claude, Cursor or any agent framework and the agent verifies its own work before it reports done, a deterministic verdict it can iterate against, with AI never part of the verdict. Every connected run is logged: your system of record for what an agent tried to ship and how often it was stopped.
Your ORM writes the SQL. Bolvrk checks what it wrote.
An @@index line in a Prisma schema becomes a plain CREATE INDEX, which holds a SHARE lock on the table for the whole build. Nothing in the schema file says so, the reviewer approves the schema file, and every framework defaults away from the safe form. So the check runs on the SQL the framework generated, in the folder it keeps it.
No files named, no config: npx bolvrk check finds the layout, and the GitHub Action does the same with an empty migrations input. Prisma and Drizzle also say which database they target, so a SQLite project gets the SQLite corpus without a flag, and a surrealdb-migrations project gets the SurrealDB corpus the same way. Rails, Django, Knex and TypeORM keep no SQL on disk, so bolvrk capture runs their migrate command against a throwaway Postgres and checks what it executed. How it works.
- Prisma
prisma/migrations/*/migration.sql - Drizzle
drizzle/*.sql - Supabase
supabase/migrations/*.sql - Flyway
V*__*.sql - Liquibase
formatted SQL changelogs - Hasura
migrations/**/up.sql - dbmate
db/migrations/*.sql, up section - golang-migrate
*.up.sql - sqlx
migrations/*.sql - Atlas
migrations/*.sql + atlas.sum - Sqitch
deploy/*.sql - Marten
db-patch output, or capture - surrealdb-migrations
migrations/*.surql, SurrealDB
Secrets caught before the commit
A seeded admin with password 'admin', a role created with its password inline, a Stripe key in an INSERT: committed, reviewed, and kept in git history forever. The BC rules catch them before the commit, and every finding masks the value.
The same rules run over any file with bolvrk secrets. Published vendor formats only, never entropy guesses, so a uuid or a bcrypt hash stays silent. A credential scan never leaves your machine.
.envDATABASE_URL=postgres://app:hunter2@db.internal/app
STRIPE_SECRET=sk_live_51H8zK2eZvKYlo2C…
JWT_SECRET=correct-horse-batterynpx bolvrk secrets ".env*" "src/**"
3 findingsBC003 critical .env:1 connection string with an embedded password, postgres://app:***@db.internal/app
BC004 critical .env:2 Stripe secret key in a literal, sk_live_***
BC006 warning .env:3 JWT_SECRET given a literal value, ***
3 findings · exit 1 · nothing left this machineA rule corpus that earns its claims
Every rule ships with fixtures in both directions, dangerous variants that must fire, safe look-alikes that must stay silent. Every claim is proven against the real thing: observed lock modes, observed rewrites, never a guess. Credential rules match published secret formats only.
ADD COLUMN region text NOT NULL;CREATE INDEX idx ON orders (region);ALTER COLUMN id TYPE bigint;ADD COLUMN uid uuid DEFAULT gen_random_uuid();ALTER COLUMN region SET NOT NULL;TRUNCATE orders CASCADE;UPDATE orders SET region = null;VACUUM FULL orders;ADD CONSTRAINT fk FOREIGN KEY (user_id) ...;CREATE ROLE app LOGIN PASSWORD 'hunter2';VALUES ('stripe', 'sk_live_51H8zK…');Deterministic, in an increasingly non-deterministic world
Real parser, never regex
Every rule runs over the database's actual parse tree. What parses in production parses in Bolvrk, and AI output never enters the verdict.
Checked against your schema
On a paid plan, findings are refined against your table sizes, foreign keys, and column types, read from catalogs in a read-only transaction, from the replica or shadow database you point us at. Findings about your database, not a hypothetical one.
Claims proven, not asserted
Every lock and rewrite claim is validated empirically against a live database in CI, observed lock modes, observed rewrites.
Every connected run, remembered
The cloud is your system of record: every check from every connected client lands in the run log, and Insights rolls it up, which rules fire most, how the clean-run rate trends, where the process is drifting. Recurring findings are process problems, not people problems; now they're visible.
Pricing
Startup
$29/month
Flat per team, never per seat, self-serve, no sales calls
- Everything in Free
- The full corpus: every rule, on every check
- Live-schema (tier-2) refinement: table sizes, traffic, foreign keys
- 2 stored connections
- Insights over the last 30 days
- Email support
Team
$99/month
Govern it as a team, protect more surfaces
- Everything in Startup
- Team policy: the block threshold and per-rule overrides, on every connected check
- 8 stored connections
- Insights over the last year
- Migration rehearsal: how long each change would block traffic on your actual tables, in the PR
- Database health: opt any connection into a weekly audit for unused, redundant and invalid indexes, unindexed foreign keys and unanalysed tables, or run one on demand
- Hosted MCP server: the verifier as a tool inside Claude, Cursor and agent frameworks
- Email support
Scale
$199/month
Every database, all of the history
- Everything in Team
- 25 stored connections
- Insights, unlimited
- Priority support
Enterprise
Custom
Your limits, your terms, your servers
- Everything in Scale
- On-prem: one executable, one config file, your Postgres. Nothing leaves your network
- GitHub Enterprise Server sign-in
- Custom connection limits, set by us for you
- Invoicing & procurement support
- Direct line to the team
Prices in USD, flat per team. VAT is added at checkout where it applies; EU businesses with a VAT number are not charged VAT.
Free, forever
$0
For every individual and open-source project
- Open-source CLI with the free rules, locally
- The free rules, in the cloud: run log, PR comments, notifications
- Sign-in, team and tokens, the GitHub Action, findings feedback
- Unlimited checks: validation is never metered
- Insights start on Startup: the run log itself is kept on Free
SET NOT NULL.orders, useCREATE INDEX CONCURRENTLYin its own migration.3 findings · exit 1, one evolving comment, not a pile.