Database rescue

Your database is a mess. We fix it without losing data.

A database that grew one AI prompt at a time usually has three or four tables doing the same job, half of them with no foreign key back to the others, and at least one policy that looks like security but doesn't actually restrict anything when you test it. None of this is visible from the UI, which is exactly why it goes unnoticed until a query times out or a security researcher finds it first. We map what's actually there, not what the schema file claims is there, and fix it without touching data you need.

Get a flat-price quote for Database Is a Mess — We Clean It Up Without Downtime

Quote back in 24 hours. No call required first.

If you see this, this is you

The signals.
What they actually mean.

There's a `users` table, a `Users` table, and a `user_profiles` table.

Each one probably got created by a different prompt solving its own immediate problem, with no check for whether something similar already existed.

A page loads slower every month as the data grows.

Usually a missing index on a column being filtered or joined on frequently — a query that's fine at 500 rows and unusable at 50,000, which is exactly when founders notice.

One query fires a hundred times to render one page.

The N+1 pattern — fetching a list, then fetching related data one row at a time in a loop instead of one query with a join. Extremely common in AI-generated CRUD code.

Nobody knows what the current schema actually looks like.

No migration history, no source of truth — changes were made directly against the database as needed, so the code's assumptions and the database's actual shape have quietly drifted apart.

A row-level security policy exists but doesn't restrict anything when tested.

A policy that references the wrong column, or defaults to allowing all reads, looks like protection in the dashboard and does nothing in practice. We test every policy against an actual unauthenticated request, not just check that one exists.

Deleting a record here doesn't delete related records there.

Missing foreign key constraints or cascade rules mean orphaned data accumulates quietly, invisible until a report or an export surfaces rows that shouldn't exist anymore.

Our process

Five steps. 14 days.

012 days

Audit

We connect to the actual database, not the schema file, and map real tables, indexes, foreign keys, and RLS policies against what the application code assumes exists.

021 day

Triage

Keep, rewrite, delete. Database cleanups usually run 55/30/15 — a meaningful chunk of tables and columns are genuinely dead.

035–8 days

Foundation

Migrations get tracked properly going forward. Indexes added where queries need them. Duplicate tables consolidated with data preserved. RLS policies tested against real unauthenticated requests and fixed where they don't actually restrict anything.

042–3 days

Migration

Every schema change runs against a copy first, verified, then applied to production with a rollback path, no direct edits against live data.

051 day

Handoff

Documented schema, migration history from this point forward, and a short note on what each table actually does — useful the next time someone's tempted to create a fifth users table.

What we do with the code

Three piles. Honest splits.

Keep

55%

Tables and data that are correct and actively used, just missing indexes or constraints.

Rewrite

30%

Duplicate or drifted tables that need consolidating, RLS policies that need to actually work.

Delete

15%

Genuinely dead tables and columns from abandoned features nobody remembered to remove.

Verdict

Who this is for.

Database problems are the ones founders notice last, because a messy schema doesn't show up in the UI. It shows up as a slow page, or a security researcher's email, or a support ticket about data that shouldn't exist. By the time it's visible, it's usually been accumulating for months. The fix is rarely a rebuild. It's consolidating duplicate tables, adding the indexes queries actually need, and testing every RLS policy against a real unauthenticated request instead of trusting that it exists means it works. All of that is doable without downtime and without touching data you need to keep. If your queries are fast and every RLS policy has actually been tested against a logged-out request, you're in better shape than most. If you're not sure, that uncertainty is the thing worth resolving before it resolves itself the hard way.

FAQ

Questions founders ask.

Will we lose any data during the cleanup?

No. Every change runs against a copy first and gets verified before touching production. Consolidating duplicate tables preserves the data, it doesn't discard it.

How do you know if our RLS policies actually work?

We test each one against a real logged-out, unauthenticated request. If that request can read or write something it shouldn't, the policy is broken regardless of what the dashboard shows.

What's an N+1 query and why does it matter?

It's firing one query per row in a loop instead of one query with a join — fine with ten rows, unusable with ten thousand. It's one of the most common causes of a page that used to be fast and now isn't.

Do we need downtime for this?

No. Migrations are applied carefully with a rollback path, and we verify each change before moving to the next, so the app stays live throughout.

How do we stop this from happening again?

Tracked migrations going forward, so schema changes go through a reviewable process instead of ad hoc edits against live data.

Ask anything

Got a question about database rescue?

Frequent questions

Valery Satsura

Valery Satsura

CEO · Start Matter · usually replies in minutes

Hey, I'm Valery. Ask anything about database rescue. I usually reply in minutes.

Engagement shape

This is one of our services.

Same engagement, on the services index: Vibe Code Rescue from $500. Quote in 24 hours, audit free for 48 hours.

Other ways we engage

Not ready for a full rescue?
Start smaller.

Vibe-coded rescue

Your AI-built MVP is breaking. We rebuild without throwing it away.

14 days · $500–$12.5K

Read the scenario

Agency transfer

Your dev team stopped shipping. We pick up where they failed.

14 days · $500–$15K

Read the scenario

Lovable rescue

Lovable shipped fast. We fix what's actually broken underneath.

14 days · $500–$12.5K

Read the scenario

Bolt.new rescue

Bolt shipped it in the browser. We fix what breaks outside it.

14 days · $500–$12.5K

Read the scenario

Replit Agent rescue

Replit Agent built it fast. We fix what it broke along the way.

14 days · $500–$12.5K

Read the scenario

Cursor rescue

Cursor moved fast in your codebase. We check what it moved.

14 days · $500–$12.5K

Read the scenario

v0 rescue

v0 built the UI. We build what it was never meant to.

14 days · $500–$12.5K

Read the scenario

Claude Code rescue

Claude Code followed most of your rules. We fix the rest.

14 days · $500–$12.5K

Read the scenario

Windsurf rescue

Windsurf doesn't exist anymore. The codebase it built still does.

14 days · $500–$12.5K

Read the scenario

Crash rescue

Your app keeps crashing. We find why, not just where.

14 days · $500–$12.5K

Read the scenario

Feature-velocity rescue

Every new feature breaks three old ones. We untangle why.

14 days · $500–$12.5K

Read the scenario

Test coverage rescue

Zero tests. We add coverage where a bug actually costs you.

14 days · $500–$12.5K

Read the scenario

Payments rescue

Stripe payments are broken. Usually it's the webhook layer.

10 days · $500–$8K

Read the scenario

Cost rescue

Your bill tripled and nobody knows why. We find the leak.

7 days · $500–$6K

Read the scenario

48-hour audit

Just the audit. No rebuild.

2 days · from $500

Written report on what your repo has and what it lacks. You decide who fixes it.

Request the audit

One feature

Ship a single feature.

1–2 weeks · $1.5K–$4K

Scoped to one workflow. Tests included. Your repo stays the way you left it.

Scope the feature

Fractional CTO

A senior in the room.

Monthly · from $1K

Architecture review, hiring help, code review on every PR. Half-day per week.

Start a conversation

Send us the repo.
We reply in 48 hours.

Read-only GitHub access is fine. One-page audit comes back inside two days. No charge for the audit.

Get a flat-price quote for Database Is a Mess — We Clean It Up Without Downtime

Quote back in 24 hours. No call required first.