Supabase schema prompts in Cursor with Git-reviewed migrations
Learn a safe Cursor Supabase schema prompt workflow: Git-tracked migrations, RLS prompts, Supabase CLI deploys. No AI access to production.
By Faisal Karkoh · Published: 2026-10-05T21:37:59.943Z · Last updated: 2026-10-05T21:37:59.943Z
What you will set up: a safe Cursor → Supabase schema workflow
This guide shows how to use Cursor to design and write Supabase schema and RLS changes without ever giving AI direct access to your production database. You will set up a Git-first workflow where:
- business requirements are written down in a schema brief
- Cursor proposes a relational model and migration plan against that brief
- Cursor is constrained to editing only migration or declarative schema files under
supabase/
- Supabase CLI applies your migrations to a local or linked dev database for verification before you run them against staging or production
- schema and RLS changes go through pull requests before any
supabase db commands touch production
The core rule: treat Cursor like a SQL editor and reviewer that never sees a production connection string. Supabase CLI and Git are the enforcement points for anything that can damage data or RLS.
This pattern fits into a broader recommendation across this site: keep AI tools away from live infrastructure and route all risky changes through Git and CLI. If you are wiring Cursor or other agents into CI as well, the guide to running AI coding agents inside GitHub Actions safely shows how to extend the same principle to your pipelines.
Why you should never let Cursor write to Supabase directly
There are already public examples of AI-generated Supabase SQL causing real damage: overly broad policies like USING (true), recursive RLS that locks everyone out, or migrations that drop tables and break auth flows. Community posts on Supabase and Reddit describe issues such as infinite recursion in RLS and unexpected access from mis-scoped policies, often after pasting AI output into the SQL editor or wiring an agent straight to the database.
Supabase exposes each project as a managed Postgres instance with its own resources and backups. Once a destructive migration is applied to production, rollback is not a single click: even with backups, restoring to an earlier point can involve downtime and loss of data written after the backup. Supabase’s billing FAQ explains that each project includes its own database, Auth, Storage, Edge Functions, and Realtime resources; in practice, that means schema changes to a project’s database can affect how those other features behave in that project.
This article focuses on a safer pattern: Cursor acts purely on code in your repository (migrations, declarative schemas, tests). Supabase CLI is the only process allowed to talk to your databases, and only after humans have reviewed the changes. For an end-to-end walkthrough of how this sits alongside API, Auth and type migrations, see the Git-driven Cursor Supabase workflow for reviewed schema, RLS and type migrations and the broader Supabase prompt workflow for secure Auth and Postgres.
There are two conceptual patterns:
- Direct AI writes to DB: Cursor or an MCP tool gets service-role keys and runs arbitrary SQL against Supabase. Fast, but a single bad policy or
DROP TABLE can compromise production.
- Git-driven migrations: Cursor edits migration files or
schema.sql. Humans review diffs. Supabase CLI applies migrations to dev, staging, then production. Problems are caught before production.
The rest of this guide documents the Git-driven option in detail.
Setup assumptions and basic repo structure
The workflow assumes:
Supabase’s own SQL Editor in Studio is powerful, but in this workflow you treat it as effectively read-only in production and channel all schema changes through Git-tracked migrations instead.
The Supabase declarative schema docs illustrate how schema SQL lives under supabase/ as the source of truth, reinforcing the guide’s recommendation to keep schema in version control and generate migrations from those files.
- a Supabase project per environment (at least dev and production)
- Supabase CLI installed and linked to your project
- a Git repository containing your app code and a
supabase/ directory
- Cursor as the primary editor for schema work
The Supabase declarative schemas guide recommends treating your schema SQL files under supabase/schemas/ as the source of truth and generating migrations from those files with supabase db schema declarative sync, which compares the schema files against your migration history rather than a live database. The same guide also documents pulling an existing schema into declarative files, for example by running a supabase db dump or related pull commands, before switching to schema-first edits.
This guide works with either raw migration SQL files under supabase/migrations or a single declarative schema file under supabase/schema.sql plus generated migrations. If you are still deciding whether Supabase itself is the right backend for your project, you may want to pair this with the Supabase review for AI builders, which covers limits, pricing and when a managed Postgres backend is the right default.
Cost and risk overview: why Git-first matters
Supabase pricing shapes the cost side of this workflow, while Git-first migrations shape the risk side.
Supabase Free vs Pro for schema experimentation
| Plan |
Price (per project / month) |
Key limits relevant to schema |
Implication for this workflow |
| Supabase Free |
$0 |
As of October 5, 2026, the Supabase Free plan is $0 per project per month and includes 50,000 monthly active users, a 500 MB database on shared compute (500 MB RAM), 5 GB egress, 5 GB cached egress, 1 GB file storage, unlimited API requests, community support, and up to 2 active projects per organization, with projects paused after 1 week of inactivity(Supabase pricing) |
Good for dev and experimentation if you keep schema compact and run tests locally. |
| Supabase Pro (first project) |
From $25 |
As of October 5, 2026, the Supabase Pro plan starts at $25 per project per month for the first project (additional projects from $10/month) and includes 100,000 MAU then $0.00325 per additional MAU, 8 GB database disk then $0.125 per additional GB, 250 GB egress then $0.09 per additional GB, 250 GB cached egress then $0.03 per additional GB, and 100 GB file storage then $0.0213 per additional GB(Supabase pricing) |
Typical production tier; schema inefficiency mainly shows up as extra disk cost and migration complexity. |
Cursor token costs for schema work
According to Cursor’s Composer 2 announcement, as of October 5, 2026 the Composer 2 Fast variant is priced at $1.50 per 1 million input tokens and $7.50 per 1 million output tokens(Cursor blog).
| Usage level |
Assumed tokens / month |
Estimated Cursor model cost |
Notes |
| Light schema work |
0.5M input, 0.25M output |
$0.75 input + $1.88 output = ~$2.63 |
Occasional migrations, a few RLS prompts per month. |
| Heavy schema cycles |
2M input, 1M output |
$3 input + $7.50 output = ~$10.50 |
Matches the scenario in the brief: intensive prompt-driven design. |
On the Pro plan, Supabase includes 8 GB of database disk per project and currently bills additional disk at $0.125 per extra GB (per the pricing page)(Supabase pricing). In practice, the more significant downside of careless AI-driven schemas tends to be long-term migration complexity and security bugs rather than incremental disk charges. If you are comparing Cursor’s costs here with other AI coding tools, the Cursor, Codex and Claude Code cost breakdown has concrete per-seat and CI examples.
Step 1: write a Supabase schema brief before opening Cursor
Start with a human-readable brief that encodes business requirements before any SQL exists. This pushes design decisions out of the model’s hidden context and into explicit text that can be reviewed and versioned.
Schema brief template
Create a file like design/schema-briefs/<feature>.md and use a repeatable template:
# Feature name
User-facing name and a one-sentence goal.
## Business context
- Who uses this feature?
- What problem does it solve?
- Any compliance or auditing requirements?
## Core entities and examples
List core nouns and a few realistic rows for each.
Example:
- Tenant: "Acme Corp", "Beta LLC"
- User: "owner@acme.com" (owner), "ops@acme.com" (operator)
- Subscription: monthly, USD, active/cancelled
## Access patterns (queries)
- How does the UI list/filter/sort entities?
- What joins are common?
- What should never be allowed (e.g. cross-tenant reads)?
## Multi-tenancy model
- Row-level tenant_id? Separate projects? Something else?
## Data retention and volume
- Expected rows per table after 1, 12, 36 months.
- Any legal retention/deletion rules?
## Auth and RLS requirements
- Which tables are public/anon readable?
- Which tables should be accessible only via service-role API keys?
- Specific rules per role (user, admin, support, etc.).
## Non-goals
- Features or entities explicitly deferred.
This brief is a primary defence against AI inventing entities or access paths that are not wanted. It also underpins cost estimates: row counts and retention feed into disk and MAU calculations later.
Step 2: prompt Cursor for a relational model and migration plan
Once the brief exists, open Cursor and point it at that file. At this stage, do not ask for SQL yet. Ask for a model and plan that can be critiqued.
Prompt: propose tables and relationships only
Use a prompt like this in a Cursor chat tied to your repo:
You are assisting with Supabase Postgres schema design.
Context:
- Supabase is the backend; we use RLS heavily.
- All schema changes must be implemented as SQL migrations in supabase/migrations/.
- We do NOT run SQL directly against production.
Task:
1. Read the business brief in design/schema-briefs/<FEATURE>.md.
2. Propose a relational data model for Supabase ONLY as:
- tables (name, purpose)
- key columns with tentative types
- relationships (FKs)
- indexes needed for the access patterns in the brief.
3. Explicitly call out:
- how multi-tenancy works (tenant separation)
- any tables that must NEVER be exposed to anon users.
4. Do NOT write SQL yet. Respond in Markdown with tables and bullets only.
Constraints:
- Assume Supabase Auth with users identified by auth.uid().
- Prefer normalized schemas unless the brief strongly prefers denormalisation.
- Be conservative about logging tables that could grow very fast.
This stage surfaces misalignments early. Table names, column types, and multi-tenant design can be reviewed against the brief before SQL exists.
Prompt: migration plan before code
After the relational model looks correct, ask Cursor to propose a migration plan:
Using the agreed data model, draft a step-by-step migration plan.
Output:
- A numbered list of migration steps.
- For each step, specify which tables/columns/constraints are created or altered.
- Any data backfill or data-movement steps.
- A rollback idea for each step (even if it requires a follow-up migration).
Rules:
- Still no SQL.
- Separate clearly what can be done online vs might need a maintenance window.
Only once the model and plan are accepted in plain language should the workflow move on to code generation.
Step 3: constrain Cursor to a single migration or schema file
The next step is to produce SQL, but with a hard constraint: Cursor may only modify one migration file (or the declarative schema file) at a time. This eliminates whole-repo, free-form actions.
Create the migration shell first
In a terminal, create a new migration:
supabase migration new add_billing_feature
This will create a file such as supabase/migrations/20261005120000_add_billing_feature.sql. Open this exact file in Cursor.
Cursor edit-mode prompt for DDL only
Now use a precise prompt in Cursor, with the migration file active in the editor:
Goal: Fill this ONE migration file with SQL for the "Billing" feature.
Context:
- Use the agreed data model and migration plan from our earlier messages.
- This file is supabase/migrations/20261005120000_add_billing_feature.sql.
- We use Supabase Postgres; RLS will be defined separately in a later migration.
Hard constraints:
- Edit ONLY this file. Do not touch any other files.
- Write plain SQL compatible with Supabase Postgres.
- Include IF NOT EXISTS guards where safe for tables, indexes and constraints.
- Do not drop or rename existing tables or columns unless explicitly specified in the brief.
- Do NOT insert test data.
Requirements:
- Create all new tables, constraints and indexes for this feature.
- Name constraints and indexes deterministically.
- Add comments on tables/columns for future maintainers.
At the top of the file, add a comment block summarising the intent of this migration.
Generate the SQL, then inspect it carefully. Look especially for unintended DROP, CASCADE, or renames.
Declarative schema variant
If the Supabase declarative schema approach is used, the constraint looks similar but targets supabase/schema.sql:
Goal: Update supabase/schema.sql to include the new Billing feature.
Constraints:
- Edit ONLY supabase/schema.sql.
- Keep existing objects intact unless the brief explicitly calls for changes.
- Do NOT drop or comment out existing tables.
After editing, the schema will be the source of truth used by:
- supabase db schema declarative sync # to generate migrations
Focus on DDL; no data migrations here.
Afterwards run:
supabase db schema declarative sync
to produce migrations from the updated declarative schema, as described in Supabase’s declarative schema guide(Supabase docs).
Step 4: run Supabase CLI locally and fix failures
Once the migration file or declarative schema is ready, the next enforcement point is Supabase CLI running against a local or dev database.
Apply migrations locally
From the project root:
# Start local Supabase (if using the local dev stack)
supabase start
# Apply migrations to local database
supabase db reset # wipes and re-applies all migrations
The supabase db reset path ensures the database can be recreated from migrations alone, which is key to long-term maintainability. Any syntax errors or dependency issues will surface here rather than against production.
Use Cursor to debug failed migrations
If the CLI errors, use a narrow prompt:
We ran `supabase db reset` and got this error:
<paste error output>
Open supabase/migrations/20261005120000_add_billing_feature.sql ONLY and:
- Explain the cause of the error.
- Propose a minimal edit to fix it.
Do not modify any other files.
Repeat until supabase db reset completes cleanly.
Step 5: generate RLS policies with a dedicated prompt protocol
RLS policies are the most dangerous place to use AI casually. Community posts on Supabase frequently call out recurring issues such as insecure defaults, policies that use USING (true), or logic accidentally granting cross-tenant access.
A safer pattern is a two-phase RLS workflow:
- RLS design as text: describe required access clearly.
- RLS SQL generation in a dedicated migration, plus a “red team” prompt to attack those policies.
RLS design brief per table
Add a section to the feature brief for each protected table:
### RLS for table: invoices
Actors:
- tenant_user: authenticated user belonging to a tenant
- tenant_admin: admin user with additional rights
- support_user: internal support staff using a service-role key via a backend
Rules:
- tenant_user: can SELECT only invoices for their own tenant_id.
- tenant_user: can INSERT invoices only for their own tenant_id.
- tenant_user: cannot UPDATE or DELETE invoices once created.
- tenant_admin: can UPDATE invoices for their tenant_id but not DELETE.
- support_user: can SELECT across all tenants but cannot write.
Non-goals:
- No anonymous access to invoices.
- No cross-tenant READ or WRITE for any non-service-role context.
Create a dedicated RLS migration file
Create a new migration:
supabase migration new add_billing_rls
Open the created file, for example supabase/migrations/20261005123000_add_billing_rls.sql, in Cursor.
Prompt: generate conservative RLS policies only
Goal: Define RLS policies for new Billing feature tables.
Context:
- See RLS requirements in design/schema-briefs/<FEATURE>.md.
- We are editing ONLY supabase/migrations/20261005123000_add_billing_rls.sql.
- Supabase Auth identifies the current user with auth.uid().
Hard constraints:
- Enable RLS explicitly on each protected table.
- Create separate policies for read, insert, update, delete.
- NEVER use `USING (true)` or `WITH CHECK (true)`.
- All tenant-bound access must filter by tenant_id linked to auth.uid().
- Do NOT grant any access to anon role for tenant data tables.
Output:
- SQL to enable RLS on each relevant table.
- Policy definitions with clear names and comments.
- No data changes, no table DDL.
Review every policy line. Confirm that:
- no policy allows unrestricted
SELECT or INSERT without a tenant filter
- there are no implicit global policies that override more restrictive ones
- service-role use is limited to controlled backends
Prompt: RLS red-team review
After generation, copy the RLS SQL into a Cursor chat (or keep the file open) and ask Cursor to attack it:
You are a security reviewer for Supabase RLS.
Here is the current RLS SQL for the Billing feature:
<paste RLS migration contents>
Tasks:
1. List all ways a malicious user could try to:
- read data from other tenants
- write data into other tenants
- bypass write restrictions (e.g. updating immutable rows)
2. For each potential issue, say whether the current policies block it.
3. Flag:
- any policy that uses `true` in USING/WITH CHECK without tenant filters
- any policy that grants access to `anon` or `public` roles
- any policy that relies on client-provided tenant_id without verifying link to auth.uid().
4. Propose concrete policy changes (in SQL) for each real weakness.
Use this critique to refine the RLS migration until there are no obvious privilege escalation paths.
Step 6: local tests and auth flows before touching production
Before any migration goes near production, define stop conditions that must be satisfied in the dev environment.
Stop conditions in Git and CLI
Require at least:
- Git cleanliness: schema brief, migration files, and any updated types or code are committed on a feature branch.
- CLI success:
supabase db reset (or supabase db push against dev) runs without errors.
- Self-check: Supabase Studio for the dev project shows the new tables, constraints and policies as expected.
Auth and RLS functional tests
Implement small integration tests or manual scripts that exercise the key flows. For example:
- auth: sign up as user A and user B, seed separate tenants, and ensure each only sees their own data.
- RLS: attempt cross-tenant reads and writes and confirm they fail.
- rate limits: be aware of Supabase Auth rate limits such as 2 emails per hour with the built-in email provider per project, 30 SMS messages per hour per project, and 30 sign-up/sign-in related requests per 5 minutes per IP address, with configuration options for custom SMTP, hooks, or different limits(Auth rate limits) when scripting tests to avoid hitting soft limits.
Cursor can generate test harnesses (for example, small Node/TypeScript scripts, or Postman collections) that run against the dev project, but environment variables should be kept out of Cursor’s context. If you want a broader, prompt-first testing and rollout pattern around this, the AI development workflow from prompt to production article walks through how to align agents, Git branches and deployment targets.
Step 7: pull request review and staged deployment
Once tests pass locally, move to Git-based review.
PR contents and review checklist
Open a PR that contains only:
- the schema brief changes (for documentation)
- new or updated
supabase/migrations/ files or supabase/schema.sql
- any code changes needed for the app to compile and run with the new schema
A review checklist can include:
- No accidental drops or renames of existing tables/columns unless explicitly intended.
- RLS policies contain no
USING (true) or similar blanket expressions.
- Multi-tenant filters use tenant identifiers derived from
auth.uid() or server-side mapping, not client-provided IDs alone.
supabase db reset works from a clean checkout.
Deploy using Supabase CLI
After merging to main:
- apply migrations to a staging or pre-production Supabase project with
supabase db push --linked (pointing the CLI at the staging project)
- run the same auth and RLS tests against staging
- only then apply migrations to production with Supabase CLI against the production-linked project
This keeps the same code paths for dev, staging and production, and continues to avoid direct dashboard SQL for anything irreversible.
How this protocol mitigates common AI + Supabase failure modes
Several failure modes show up repeatedly in community stories. The protocol above addresses them explicitly.
1. Insecure RLS like USING (true)
Risk: a policy such as USING (true) grants blanket access. Builders on Supabase’s subreddit have called this out as a frequent anti-pattern.
Mitigations in this workflow:
- RLS design is written in a brief before SQL.
- RLS prompts explicitly ban
USING (true) and require tenant checks.
- Red-team prompts ask Cursor to find over-permissive policies.
- PR checklist flags any policy lacking a tenant filter or role scoping.
2. Dropped tables or destructive schema changes
Risk: AI-generated migrations include DROP TABLE or ALTER TABLE... DROP COLUMN where additive changes were expected, leading to data loss.
Mitigations:
- Migration prompts forbid destructive changes unless the brief explicitly calls for them.
- Humans inspect migration files; destructive statements stand out in diffs.
supabase db reset validates that the full migration chain can rebuild the database, ensuring there are no hidden dependencies on dropped objects.
3. Broken auth flows
Risk: schema or RLS changes interfere with auth-related tables or flows, causing sign-ups or token refreshes to fail. Supabase Auth rate limits and MAU counting tie into these flows(MAU docs).
Mitigations:
- Briefs include explicit non-goals, such as “do not touch auth tables”.
- RLS work is scoped to feature tables, not core auth tables.
- Auth regression tests (sign-up/sign-in, token refresh) run after migrations on dev and staging.
4. Unbounded logging and disk growth
Risk: AI-generated schemas introduce heavy denormalised logs, driving disk usage faster than expected. On Pro, disk overage is billed at $0.125 per GB beyond the 8 GB included(Supabase pricing).
Mitigations:
- Schema briefs include expected row counts and retention policies.
- Prompts nudge Cursor towards normalized schemas and conservative logging tables.
- Cost scenarios estimate the impact of retention on disk cost, encouraging pruning or summarisation.
Where Cursor Projects and MCP can fit in
Cursor documentation describes Projects as agents that can take on larger work items such as “a feature” or “a migration”(Cursor docs). For teams repeatedly evolving schemas, a Project can orchestrate some of the steps above, as long as it stays within the same safety rails:
- Projects manipulate only documented files (
design/schema-briefs, supabase/schema.sql, supabase/migrations/).
- Projects never receive Supabase connection strings or service-role keys.
- Any automated CLI or MCP operations run in a CI context that cannot touch production directly, similar to patterns described for secure MCP apps that keep Supabase behind Git and CLI.
Model Context Protocol (MCP) integrations documented by third parties allow Cursor to query Supabase schemas via a dedicated tool server. Many practitioners keep these integrations read-only for production databases, using them to inspect schema and generate migrations that are then applied via CLI, matching the Git-first pattern here.
What changes the decision
The core recommendation is a Git-first, human-reviewed Cursor workflow. A few conditions legitimately change that decision:
- Desire for fully automated schema evolution: if the team wants nightly, zero-touch schema refactors, this guide is not sufficient. In that case, an agent that runs in CI, opens PRs with migrations, and passes additional safety checks may be more appropriate.
- Non-Supabase backends: if Neon, PlanetScale or an ORM-managed database is used instead of Supabase, a Git-first and CLI-first pattern is still desirable, but the details (RLS, Supabase CLI commands) differ.
- Different IDEs: if a team standardises on VS Code with GitHub Copilot or another coding assistant, the same brief → plan → migration → RLS → PR pattern can be applied there instead of Cursor.
- Strict DBA control: some organisations require human-written SQL only. In that setting, Cursor can still help refine the schema brief and review migrations for consistency or query patterns, while SQL itself stays manual.
Decision tree: how much access should AI get?
| Pattern |
AI access to DB |
Change tracking |
Risk level |
Rollback difficulty |
| Direct AI writes (not recommended) |
Service-role keys, live SQL |
Ad-hoc |
High |
Hard: manual patches or full restore |
| Git-first migrations with Cursor (this guide) |
No direct access; CLI only |
Git + Supabase migrations |
Moderate |
Medium: revert migrations, reset dev, carefully migrate prod |
| No AI on schema |
None |
Manual migrations |
Low |
Medium: same as above, but slower iteration |
Putting it all together
A production-grade way to combine Cursor with Supabase schema and RLS changes is to treat Cursor as a specialised editor and reviewer for migration and schema files only. The workflow is:
- Write a structured business and RLS brief per feature.
- Have Cursor propose a relational model and migration plan, with no SQL.
- Create migration or declarative schema files manually, then let Cursor fill them under strict constraints.
- Generate RLS in a dedicated migration, then red-team it with targeted prompts.
- Run Supabase CLI locally, test auth and access patterns, and commit everything to Git.
- Review via PR, then apply migrations to staging and production with Supabase CLI only.
This pattern avoids giving AI direct access to production, keeps schema evolution visible in Git, and builds in explicit stop conditions and review points that align with the way Supabase itself recommends managing database schemas.
For a broader view of Cursor + Supabase safety patterns beyond prompts, including CI options and repository structure, see the existing Git-driven Cursor Supabase workflow article on this site, which this prompt protocol slots into as the schema and RLS layer, and the Cursor rules for a real production repo guide for broader IDE-side guardrails.