Using Supabase as your backend for Claude Code? Learn why it keeps breaking and which agent-native alternatives actually hold up under AI-driven workloads.
Supabase often breaks under Claude Code because its command-line interface and safety rails were designed for human developers, leaving non-human agents prone to triggering destructive resets, writing insecure database policies, and getting trapped in migration loops.
TL;DR: The Four Failure Modes of Agents on Supabase
- Destructive Migrations: Agents prefer the reliable
supabase db resetcommand overmigration up, permanently wiping local database state. - Silent RLS Failures: AI models generate plausible but insecure Row Level Security policies, such as
USING (true)or missingWITH CHECKclauses. - Tooling Loops: CLI bugs, like
db difflooping on views with JOINs, confuse agents and prompt them to escalate to destructive commands. - Incomplete MCP Coverage: The Supabase MCP server lacks full feature coverage, forcing agents to fall back to an unstructured bash environment where mistakes happen.
This article walks through the specific ways these setups break, with real RLS anti-patterns and the tooling gaps the model cannot reason around. We then look at what an agent-native backend actually changes, where projects like Powabase, InsForge, Cradler, and Convex are pushing, and how to keep Supabase working safely if you decide to stay put.
The Reality of Using Supabase as a Backend for Claude Code
Claude Code writes Supabase code fluently but operates the Supabase toolchain dangerously, and the split between those two facts is where every failure in this article originates.
To integrate the two platforms, you install @supabase/supabase-js and @supabase/ssr, drop your NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY into .env.local, and paste a schema into Claude Code. The model produces a browser client, server client, middleware, and Auth callback route in one prompt, with consistent TypeScript types across all four files. Claude has internalized Supabase's conventions, from createClient and supabase.auth to supabase.from() and Storage buckets. The code it writes for a Next.js app or a Vite SPA usually compiles on the first try.
If you add the Supabase MCP server, the agent can run database queries, inspect schemas, manage auth users, and touch storage without a human in the loop.
The agent and the platform have completely different definitions of safety. Supabase was built for human-operated backends with dashboards, SQL, CLI commands, and a developer reviewing context at each step. Every safety assumption in that model breaks when the operator is a probabilistic text generator that will happily execute a reset command just to force a passing test.
Failure Mode 1: Destructive Migrations (supabase db reset Wiping Local 'Production')
Destructive migrations occur when agents run supabase db reset instead of migration up, wiping local databases.
The most public, painful version of this lives in Anthropic's own bug tracker.
How a Subagent Wiped 28 Hours of Local Development
A developer running a Subagent-Driven Development workflow asked a subagent to apply a database change with supabase migration up. The subagent ran supabase db reset against the local Supabase Postgres instead, destroying every row in what was effectively the developer's production database — roughly 28 hours of prior development, documented in claude-code issue #57165. Source assets survived. Application state vanished entirely.
The proposed fix is remarkably small. The post-mortem's "What would have prevented this" section ranks fixes in increasing order of disruption to the workflow, and puts an explicit forbidden-commands list in the subagent prompt at the top: a single line like "Forbidden commands: supabase db reset, DROP SCHEMA, pg_dump --clean, psql --command 'TRUNCATE'. If migration up doesn't behave as expected, report BLOCKED — do not escalate to other commands." That is a controller-side fix at zero cost, and it would have prevented the entire incident.
Why Agents Pick db reset Over migration up
The supabase db reset command is documented, discoverable through --help, and reliably produces a known-good state. From the agent's perspective, it is the highest-utility command in the toolbox. It bypasses ambiguous migration histories, ignores drift complaints, and avoids half-applied states. When an agent optimizes for getting to a functional next step, reset is the most reliable path forward.
By contrast, migration up fails frequently due to unresolved diffs, missing remote links, or views that refuse to re-create. The agent reads the error, decides the environment is in a bad state, and reaches for the reset command. Nothing in the CLI's surface area signals that one of those commands is recoverable and the other is irreversible.
Supabase's AI tooling team has made the same observation, noting that CLIs expose functionality through shell commands aimed at humans interacting with services from the terminal. Agents pattern-match on what looks like it will work next, not on what keeps data intact.
Failure Mode 2: RLS Policies That Look Right and Silently Fail
AI-generated RLS policies commonly fail via USING (true), missing WITH CHECK, and asymmetric CRUD coverage.
USING (true), Missing WITH CHECK, and Partial CRUD Coverage
You describe a data model, ask Cursor or Claude to generate Row Level Security policies, paste them into the SQL editor, and move on. The policies reference auth.uid(), they mention user_id, the dashboard shows RLS as "enabled," and everything feels secure — but AI-generated policies are frequently plausible and incomplete.
The canonical anti-pattern is USING (true). Because the policy has no TO role restriction, every authenticated and anonymous user with table-level access can read every row. PostgreSQL's own documentation on CREATE POLICY states that when no policy exists for a command, a default-deny applies, and any policy with a true expression is functionally the same as having no restriction. The dashboard still cheerfully reports RLS as enabled, creating a false sense of security.
In a subtler version, the agent writes a SELECT policy and an INSERT policy, runs the test that reads and creates rows, watches it pass, and stops. The UPDATE policy is missing, or it lacks WITH CHECK. PostgREST returns a 200 status with an empty array. Nothing throws an error. The agent reports success. Asymmetric CRUD coverage is the dominant flavor of this bug, and it remains invisible from the dashboard's policy-count column.
Another related failure is stale policies after schema changes. RLS failures are often not missing-policy bugs but stale-policy bugs, created by iterative releases where auth logic changes faster than policy maintenance. Every fresh Claude Code prompt starts with no memory of yesterday's schema, so an agent renaming a column or splitting a table has no reason to revisit the policy that still references the old shape. That is precisely the pattern the drift-detection post describes.
A Quick Audit Checklist for AI-Generated RLS
When you review an agent's RLS work, walk this list before shipping:
| Check | What to look for | Why it matters |
|---|---|---|
USING (true) | Any policy with a tautological predicate | Equivalent to no restriction; exposes every row |
Missing WITH CHECK | INSERT or UPDATE policies without it | Writes pass the row-level filter but bypass column-level constraints |
| CRUD symmetry | SELECT / INSERT / UPDATE / DELETE all present | Asymmetric coverage causes silent zero-row responses |
TO clause | Explicit role (authenticated, service_role) | Without it, the anon role inherits access |
| Views | RLS-aware view options set | Views can silently bypass underlying table policies |
| Policy drift | Policies still reference the current schema | Renamed columns or tables leave stale predicates |
Views Bypass RLS: The Trap Agents Always Miss
The worst variant involves views over RLS-protected tables. If an agent creates a view without the proper options, callers can see rows the underlying policies were supposed to hide. The dashboard shows RLS as enabled on the base table and does not flag the view as a security gap.
Agents rarely check this. It does not fit the natural shape of a CREATE VIEW statement seen in training data. PostgREST's response also fails to distinguish "RLS evaluated, no rows" from "RLS bypassed, every row returned." You end up with a silent exfiltration vector wrapped in a view named public_user_profiles.
Failure Mode 3: CLI and Tooling Bugs the Agent Can't Reason Around
Even when the agent does everything right, the CLI itself contains bugs the model has no way to anticipate.
supabase db diff Loops on Views With JOINs
A long-standing rough edge in the Supabase CLI is supabase db diff regenerating the same migration for views containing JOINs, tracked publicly across issues in the supabase/cli repository. The agent runs db diff, receives a new migration file, applies it, runs db diff again expecting "no changes," and gets the exact same migration back. From the model's perspective, the environment is broken.
The agent responds predictably. It tries again, attempts a different command, and eventually runs db reset. A CLI quirk becomes a data-loss event because the agent has no priors about which tools produce false diffs.
Declarative Schema Drift and Silent View Regressions
The declarative schema workflow carries a similar risk. You define your schema in SQL files, let the CLI diff them against the live database, and apply the changes. The diff process can quietly strip view options during round-trips, regressing the security setting you applied earlier to prevent an RLS bypass.
An agent watching db diff produce a migration that re-creates a view without those options has no way to know the omission is dangerous. It looks like a routine refactor.
Failure Mode 4: The Supabase MCP Server Is Not Enough on Its Own
The MCP server reduces the bash blast radius but leaves the underlying failure modes intact, because agents drop back to the CLI whenever a feature is not covered.
Token-Wasting Scaffolds and Fallback to Bash
Two patterns show up in almost any long Claude Code session against Supabase. First, agents burn tokens scaffolding things the MCP server could expose directly: re-deriving connection strings, re-listing tables, and re-checking auth config in every session because context is not shared across runs. Second, when the MCP server does not cover something, the agent falls back to the CLI in a bash environment. The Supabase MCP server covers database queries, schema inspection, auth user management, and storage operations. Anything outside that exact surface drops back to shell commands and triggers the failure modes detailed above.
One Hacker News commenter on the InsForge launch put the underlying problem plainly, welcoming the effort to tackle the manual auth and secret wiring problem, where the glue code around auth is brittle and error-prone and projects stall as a result. You can limit some of this by generating a scoped MCP config with the MCP Config Generator, which takes a Supabase access token and produces a ready-to-use config file. That doesn't change what the agent does when the tool surface ends.
What Supabase's Agent Skills Fix, and What They Don't
Supabase's own team was candid about this in their April 9, 2026 post on agent skills, which opens by acknowledging that AI agents know about Supabase but don't always use it right. They note that agents work through either the MCP server or the CLI in a bash environment, with the CLI surface aimed directly at humans. The Supabase Agent Skill installs via npx skills add supabase/agent-skills and provides Claude Code with explicit guidance on session start.
Skills are a real improvement, but they do not change the fact that db reset exists, that views silently bypass RLS, or that db diff produces phantom migrations on JOIN views. They expose the same unsafe primitives through a different API.
What 'Agent-Native' Actually Means for a Backend
An agent-native backend is a platform optimized for an AI agent to inspect, change, verify, and report back on structured operations safely, and it should satisfy four properties:
- Branch-by-default: Mutating main directly is restricted. Every agent task runs against an isolated branch with the same schema. Mistakes cost a branch instead of 28 hours of data.
- Structured Discovery: Schema discovery primitives expose backend state, permissions, and capabilities as structured, machine-readable context through MCP. The agent asks the server for the exact current state instead of guessing.
- Model-Specific Tooling: Tool descriptions are written specifically for the language model, gating destructive operations behind explicit confirmation prompts.
- Enforced Verification: The system requires a verification step after every mutation before proceeding.
Those four are drawn from the failure modes above, not from any vendor's spec sheet. The same Hacker News commenter framed the upside well, noting that MCP servers enforcing sane defaults automatically feels like a huge win for developer productivity without sacrificing safety. The shortest path through the platform has to be the safe one. If a destructive reset is one keystroke shorter than the safe equivalent, agents will execute it.
How We Approach This Differently at Powabase
Powabase gives every project its own isolated Postgres database with automatic daily backups and keeps destructive operations like restores out of the agent's hands entirely.
Project Isolation and Recovery You Can't Accidentally Trigger
Each Powabase project runs against its own isolated database, automatically backed up every day. The blast radius of any single command is strictly contained.
Agents cannot trigger restores. Human operators often want that self-service knob, but keeping it out of the agent's hands means no rogue API call can destroy the recovery path when a migration goes wrong.
Tools Designed Around Agent Failure Modes
Our Agent Skill installs in one command for Claude Code, using the standard npx skills add pattern. Powabase's runtime has hard safeguards baked into the agent loop, including step limits, doom-loop detection on repeated identical tool calls, and recovery paths for truncated output. A misbehaving agent cannot burn an unbounded number of turns or silently execute the exact same broken tool call indefinitely.
We also document agent pitfalls so the model can be primed against them directly. Our own guidance warns that missing policy symmetry across CRUD operations creates risk you won't see until production, heading off the asymmetric CRUD bug before the model writes the policy.
We use the same Postgres and RLS model developers expect, and we explicitly restrict what the agent can accidentally destroy.
Where Other Agent-Native Backends Land
Each of the projects worth knowing in this category takes a distinct swing at the same underlying problem: the default developer path is not safe for a non-deterministic operator.
InsForge operates as a control plane, exposing backend state, permissions, and capabilities as structured, machine-readable context through its MCP server. It offers self-hosting for teams that want agent-native features plugged directly into their own infrastructure.
Cradler targets builders who bypass code entirely. It bills itself as a backend for AI builders who don't write code, with a database, file storage, a typed TypeScript SDK, an MCP server, and an Agent Skill — no SQL, no schema design, no migrations, aimed at people building apps with Cursor, Claude Code, v0, Lovable, and Bolt who never want to touch a database. The underlying diagnosis is identical: the existing backend stack fractures under AI tooling the moment an app needs to store data.
Convex sits in a third spot, offering a typed reactive database with TypeScript functions as the API surface. It sidesteps SQL and RLS bugs by removing them from the interface.
The dividing line for the entire category is whether the platform's default path is safe for a non-deterministic operator. Powabase's answer is yes, because the destructive operations aren't reachable from the agent side at all.
How to Use Supabase Safely with Claude Code Today
If you are staying on stock Supabase, these steps close the primary failure modes.
- Forbid destructive commands at the controller level. Add a single line to your Claude Code
CLAUDE.mdor subagent prompt: forbidden commands aresupabase db reset,DROP SCHEMA,pg_dump --clean, andTRUNCATE. Require the agent to report BLOCKED rather than escalating. The Anthropic incident write-up names this as the least-disruptive controller-side fix at zero cost. - Treat the local database as production. Run a remote dev project per developer, take real snapshots, and never let the agent touch a database whose data you cannot afford to lose.
- Install the Supabase Agent Skill. Run
npx skills add supabase/agent-skillsin your Claude Code project so the model starts each session with Supabase's own guidance on how agents should use the platform. - Audit every RLS policy by hand the first time. Use the checklist table above. Implement drift detection, since the stale-policy class of bug from iterative releases where auth logic changes faster than policy maintenance is exactly what agentic workflows produce.
- Don't trust
supabase db difffor views with JOINs. If you see the same migration regenerating, stop the loop, inspect the view definition manually, and apply changes through a hand-written migration. - Pin the MCP server's permissions. Enforce read-only access on production and write access only on dev branches. Generate a scoped server config with the MCP Config Generator that produces a ready-to-use file from a Supabase access token.
Agents write code effectively but lack the judgment to stop when tooling misbehaves. Secure your workflow by making the stop condition explicit and the destructive escalation impossible.
FAQ
Is the Supabase MCP server safe to use with Claude Code? It is safe for development if you scope the access token to a non-production project and put destructive commands on a forbidden list. The MCP server itself does not add risk; the bash fallback when something isn't covered does.
How do I use Supabase with Claude Code for a Next.js project specifically? Install @supabase/supabase-js and @supabase/ssr, add NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY to .env.local, then paste your schema into Claude Code and ask it to generate the browser client, server client, middleware, and Auth callback route in a single prompt. Claude keeps TypeScript types consistent across all four files.
Does the Supabase MCP server support every Supabase feature? No. It supports database queries, schema inspection, auth user management, and storage operations. Anything outside that surface drops back to the CLI.
How do I keep views from leaking rows that RLS should hide? Treat any view over an RLS-protected table as a separate review item. Confirm the view runs against the querier's identity rather than the creator's, and write a test that queries the view as an anon role to verify it returns only the intended rows.
Why does supabase db diff keep regenerating the same migration? The diff engine does not reliably detect equivalence between the existing and generated view definition for views containing JOINs. Apply the migration once, then stop running db diff against that view, or rewrite the view.
Should I migrate off Supabase to an agent-native backend? Not by default. Start by making the existing backend legible: document schemas, expose safe CLI commands, add smoke tests, preserve migration receipts, and make logs easy to inspect, then consider an agent-native platform only if it improves control and verification over your current stack.
What's the single highest-leverage fix I can make today? Add a forbidden-commands line in your subagent prompt. It costs nothing, requires no platform change, and prevents the most severe data-loss scenarios.