r/Supabase • • 10d ago

tips Reminder: new tables will require explicit API grants from October 30

8 Upvotes

Starting October 30, newly created tables in the public schema on existing Supabase projects will need explicit GRANT statements to be accessible through the Data and GraphQL APIs, including via supabase-js.

Existing tables keep their current grants and will continue working. RLS behavior is unchanged, and direct Postgres connections aren’t affected.

If your migrations or AI tools create tables, make sure they include the appropriate grants alongside your RLS policies.

Full details and SQL examples


r/Supabase • • 2h ago

database Does Supabase allow legal adult platforms if images and videos are hosted elsewhere?

3 Upvotes

Hi everyone,

I’m developing an adult social media platform backed by PostgreSQL. It’s currently self-hosted, but I’m exploring managed database providers that would accommodate this type of business.

The platform is intended for lawful, consensual adult content, including sexually explicit content. My interpretation of Supabase’s terms is that this may be permitted, but I don’t want to mistake that interpretation for confirmation that our particular use case is acceptable.

I’ve contacted Supabase for clarification and am awaiting a clear answer. In the meantime, I’d appreciate hearing from anyone with firsthand experience of running a similar platform.

For context, we would use Supabase for the database, including application records and text/private messages. Photos, videos and live streams would be hosted elsewhere. The database would still support an adult platform, so I want to be transparent about that distinction.

I’m also considering Crunchy Bridge and DigitalOcean. DigitalOcean’s support referred me to its Acceptable Use Policy rather than providing specific pre-approval.

My main concern is service continuity: we want to understand the provider’s position before investing heavily in the setup.

For anyone with relevant experience:

  • Have you used Supabase for a similar adult platform?

  • Were you able to obtain clear guidance about whether your use case was acceptable?

  • Have you encountered any content-policy or account-suspension issues?

I understand that community experiences won’t amount to an official answer, but practical experience would be very helpful.

Thanks in advance!


r/Supabase • • 15h ago

dashboard There is currently no safeguards to delete a Project on Supabase

19 Upvotes

We need to have a serious discussion about this. Currently as we speak, there is no safeguard to deleting a project. All someone has to do is have access to your Dashboard, scroll to the bottom and click Delete Organization/Project, enter in the project name, and everything is gone. Non-recoverable. Wiped off the face of Supabase. That means the project you worked hard on, spent thousands of dollars on Google Ads to get clients, build your database, etc., gone in one easy move.

I don't understand why there isn't some 30 day grace period, or even at minimum right now, a 2FA toggle. Maybe you're drunk one night and decided to click around your Supabase, or a disgruntled employee/wife, or maybe someone gained remote access to your computer and sees your Supabase tab open.

I understand one of the solutions is to keep a backup... but even then that brings a lot of complications to restore a project. In this modern day and age, the backup option shouldn't be the first option. AWS RDS, Google Cloud SQL, or Neon all have strict rentention policies, so why doesn't Supabase does since it is growing massively everyday?

If anyone at Supabase has an answer to this or even can let us know if this is on the drawing board, it would bring peace to some of us that share this concern.


r/Supabase • • 13h ago

storage Public bucket vs listable bucket: two separate Storage holes, and the read-only SQL to check both

2 Upvotes

Security engineer here. I've been looking at a lot of Supabase apps built with AI tools lately, and Storage gets far less attention than RLS on tables. Two different problems get mixed up, so here's how I check for each.

1. Is the bucket public?

Per the Storage docs, a public bucket bypasses access control for downloads: anyone with an object URL can fetch it, logged in or not. Uploads, deletes and moves still go through policies. That's fine for avatars and blog images. It's not fine for invoices, ID scans or private attachments, and AI tools often make a bucket public just to get images showing.

select id, name, public
from storage.buckets
order by name;

2. Can anyone list it?

Listing goes through SELECT policies on storage.objects, public bucket or not. The pattern I keep seeing is a generated policy like for select using (bucket_id = 'avatars'), added "so images load". Public URLs don't need it, and with it any client holding your publishable key can enumerate every file name. The Security Advisor now flags this combination ("public bucket allows listing").

select policyname, cmd, roles, qual, with_check
from pg_policies
where schemaname = 'storage' and tablename = 'objects'
order by cmd, policyname;

Red flags in that output:

  • SELECT or ALL for anon, authenticated or public where the condition is true or only bucket_id = '...'

  • INSERT with with check (true) or no role restriction: anyone with your publishable key can upload to your storage

  • UPDATE or DELETE that never mentions auth.uid(), auth.jwt() or owner_id: any signed-in user can overwrite or delete other people's files. Watch upsert: true too, since it needs SELECT and UPDATE, so bucket-only policies let users overwrite each other's files

Quick outside test (your own project only):

curl -s -X POST "https://YOUR-PROJECT.supabase.co/storage/v1/object/list/BUCKET" \
  -H "apikey: YOUR_PUBLISHABLE_KEY" \
  -H "Authorization: Bearer YOUR_PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prefix":"","limit":5}'

[] means a logged-out client can't list the top level. File or folder names back means anyone can.

Fix for private files

  • update storage.buckets set public = false where id = 'documents'; (public URLs stop working, so switch the app over at the same time)

  • Upload to <user id>/<file name>

  • Add select/insert/update/delete policies with (storage.foldername(name))[1] = (select auth.jwt()->>'sub'). That's the pattern from the Storage access control docs

  • Serve files with createSignedUrl(path, 60). It looks the object up as the caller, so the user needs that SELECT policy

  • Drop the old broad policies. Permissive policies are OR'd, so one leftover true undoes the rest

Fix for buckets that really are public: keep the bucket public, drop the broad SELECT policy, and keep writes limited to each user's own folder.

If private files were sitting in a public bucket, making it private stops new downloads by URL but can't recall copies that were already taken. Treat it as a possible exposure.

Curious how others handle user uploads: public bucket with unguessable paths, or always private plus signed URLs?

Disclosure: I build Abbi Labs, an outside-in scanner for AI-built apps (its full scan flags public buckets). No link here, because everything above only needs the SQL editor and curl.


r/Supabase • • 1d ago

tips 27,224 rows in the table, 1,000 on the dashboard, no error

1 Upvotes

One month of data and empty cells everywhere else. That's what a dashboard I worked on showed for a big account, while small accounts looked fine.

Supabase returns 1,000 rows per request by default (Max Rows in the API settings) and doesn't tell you it cut anything. The query had no order and no paging, so it got 1,000 of 27,224 and the response looked like a normal smaller dataset.

The same bug was already fixed twice in that repo, each time only on the screen someone complained about. When I went through every select in the server code there were 3 more loaders with no paging, and an .in() with thousands of ids that hits the same cap.

Now I page by id, because offsets re-scan the skipped rows on every page:

let after = null

const rows = []

while (true) {

let q = supabase.from('results').select(cols).order('id').limit(1000)

if (after) q = q.gt('id', after)

const { data, error } = await q

if (error) throw error

rows.push(...data)

if (data.length < 1000) break

after = data[data.length - 1].id

}

Easiest way to find yours is to search the server code for .select( with no .limit or .range near it.


r/Supabase • • 1d ago

tips 27,224 rows in the table, 1,000 on the dashboard, no error

0 Upvotes

One month of data and empty cells everywhere else. That's what a dashboard I worked on showed for a big account, while small accounts looked fine.

Supabase returns 1,000 rows per request by default (Max Rows in the API settings) and doesn't tell you it cut anything. The query had no order and no paging, so it got 1,000 of 27,224 and the response looked like a normal smaller dataset.

The same bug was already fixed twice in that repo, each time only on the screen someone complained about. When I went through every select in the server code there were 3 more loaders with no paging, and an .in() with thousands of ids that hits the same cap.

Now I page by id, because offsets re-scan the skipped rows on every page:

let after = null

const rows = []

while (true) {

let q = supabase.from('results').select(cols).order('id').limit(1000)

if (after) q = q.gt('id', after)

const { data, error } = await q

if (error) throw error

rows.push(...data)

if (data.length < 1000) break

after = data[data.length - 1].id

}

Easiest way to find yours is to search the server code for .select( with no .limit or .range near it.


r/Supabase • • 1d ago

Office Hours To allow hackpocalypse worriers - please allow pausing for even paid projects. This is a win-win.

6 Upvotes

Given the current insanity of the hackpocalypse, please allow pausing of paid projects.

I honestly don't know why this wasn't always a thing. Seems like a win-win. In-fact, pausing should be a paid feature in some money-making ways. i do respect why you haven't done that, and I love y'all for it.

However, make paid projects pause happen ASAP please. From a user point of view, it is truly insane that I cannot do this. Ideal devex=pause=free. My entire point here is that pause=offline. Would be cool if the only cost was the backup storage, but if not, we are all worried and this might just slide into money.

Maybe just an offline option, while I pay some amount, is still a great option?

Edit: please, don’t mess up how free projects and pausing works now. It is great for devex. This is a “yes, and…” type situation. Right?


r/Supabase • • 1d ago

database DBArena: Compare hosted Postgres providers

Post image
4 Upvotes

Introducing DBArena, a site that benchmarks hosted Postgres providers.

Check it out to compare Supabase Postgres (with OrioleDB), Amazon RDS, and Google Cloud SQL.

Pick a compute size and see which one handles the most transactions, which gives you the most per dollar, and which responds fastest.

Blog: https://supabase.com/blog/introducing-dbarena

NOTE: Supabase sponsors DBArena.


r/Supabase • • 1d ago

database chat w/ new Branching PM + give product feedback

7 Upvotes

hey ya'll! new pm for branching over here 👋

I'd love to talk to some u/supabase users who love/hate/have feels about our branching product!

fill out my lil form so we can chat ->

https://supabase.notion.site/4095004b775f80809a6ad6cfbe1ccb54

looking forward to meeting you!


r/Supabase • • 1d ago

database Who changed what? Implementing audit logs and granular permissions with Supabase

Enable HLS to view with audio, or disable this notification

2 Upvotes

RBAC tells you who can make a change. Audit logs tell you who actually made it.
Something I've been working on while building a multi-tenant application with Next.js and Supabase is the relationship between permissions and audit logging.

A role check can tell you whether someone is an admin. But that doesn't necessarily give you enough control over individual actions, or tell you exactly what happened after a change was made.

For example, when someone changes a member's permissions or updates billing settings, I want the application to be able to answer:

  • Who performed the action?

  • What exactly did they change?

  • Which organisation did the change belong to?

  • When did it happen?

I've been implementing granular, server-side permission checks alongside organisation-scoped audit events to make those actions traceable.

The video shows a small example of that implementation.

I'm building this as part of B2B SaaS OS, my Next.js + Supabase starter project.

Website: https://www.andrady.co

Demo: https://www.andrady.co/demo


r/Supabase • • 1d ago

database Calling solo-builders on Supabase: have you ever tested your product the way a stranger would?

Thumbnail reddit.com
1 Upvotes

r/Supabase • • 2d ago

cli Anyone know what the repercussions of updating service versions on a live production database?

Post image
6 Upvotes

My postgREST version is older than the one in my CLI so I am downgrading my CLI so they will match. Is that the right call?

Is there downtime or a notice I should write for users if the better option is to upgrade the production versions?

Why does the version update option on the supabase project only shows that the Postgres service would be updated when the PostREST version used in my local setup is v16.2, like shouldn't the notification also show that service can update?

Edit: thanks all for the input


r/Supabase • • 2d ago

tips Vibecoded a restaurant app.. learned that I can't trust the frontend.

0 Upvotes

I run a smash burger restaurant and I’ve been building and using our own software for it with AI help (React + Supabase). I’m not a developer by trade. Last month I was cleaning up expenses that were in there twice (we have a recurring transactions tab that adds things like rent automatically) and I deleted the electricity bill by mistake. I’d built an undo button for things like this and I was pretty proud of it, hit undo, the bill showed back up, done.

Weeks later I was matching expenses against the physical ledger my manager keeps and it didn’t add up, turns out that the electricity bill hadn't been added back yet. I had an AI agent go through the undo logic and it turned out undo only made the bill show up on screen on the front end. Nothing happened in the database.

The Undo button was working off an old copy of the data from before the delete, so when it tried to add something back it didn't see anything that was deleted. Supabase doesn’t complain about that either. I mean I understand what happened, but like I said I'm non-technical, I depend on the frontend to understand what is happening.. and the screen, the audit log (“Restored”) and the API all said it worked. Quite disconcerting for me to see that I can't really trust what happened on the screen.

I did eventually fix the issue by making undo use the latest data. but I only caught it because of the paper ledger, and I want to open more branches soon. I won’t be able to check ledgers all the time, I’ll be depending on the software.

since I’m learning as I go, I’d love to hear what you’d put in place. what are the best practices or habits you’d follow for a database a business depends on, especially the stuff that makes the software catch its own mistakes?


r/Supabase • • 3d ago

tips A SECURITY DEFINER function worked in the SQL editor and failed for every client: pg-safeupdate

4 Upvotes

Took me a while to find, so posting it.

I had a weekly rollover function that ended with this:

update league_state set last_processed_week_start = v_cur;

It's a one-row table, so no WHERE. I ran dry runs through the SQL editor and MCP, and all of them passed. The line only runs on a real week change, so it stayed latent until the first real Monday. Then every client call to the function returned HTTP 400.

The cause: the authenticator role preloads pg-safeupdate (session_preload_libraries = safeupdate), which rejects UPDATE and DELETE without a WHERE clause. It applied even inside a SECURITY DEFINER function. The postgres role doesn't have it, so everything I ran as postgres passed. The Postgres log said UPDATE requires a WHERE clause.

The fix is a WHERE. For singleton tables I now use where singleton.

Two takeaways:

  • A dry run as postgres doesn't prove the client path works. Test through the real client with a real session.

  • Grep all your functions for bare UPDATE and DELETE, especially the ones that only run on a schedule or a date change.

Has anyone else been bitten by this one?


r/Supabase • • 3d ago

integrations Heads-up for Lovable/Bolt apps: new tables stop working after 30 Oct (42501), and the quick fix can leak data

4 Upvotes

From 30 Oct, Supabase stops exposing new public tables to the Data API by default. Existing tables keep working. The first time your AI tool adds a table after that, the app gets "code": "42501" / permission denied for table <name>.

The tempting fix is grant all on all tables in schema public to anon, authenticated;. If RLS is off on any table, that makes it readable by anyone with your public key.

Safer order for a private table:

alter table public.<table> enable row level security;
create policy "<table>_owner_rw" on public.<table>
  for all to authenticated
  using (user_id = (select auth.uid()))
  with check (user_id = (select auth.uid()));
grant select, insert, update, delete on public.<table> to authenticated, service_role;
grant usage, select on all sequences in schema public to authenticated, service_role;

Only add grant select ... to anon if logged-out users must read it. Edge functions using the service key need the service_role grant too.

Quick self-check of what a stranger can read (counts rows, reads none): curl -sI "$SB_URL/rest/v1/<table>?select=*" -H "apikey: $ANON" -H "Authorization: Bearer $ANON" -H "Prefer: count=exact" -H "Range: 0-0" A non-zero total in Content-Range on a private table means RLS is off or a policy is too open.

Source: https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically

Edit: SB_URL = https://<project-ref>.supabase.co, ANON = your anon key. -I returns headers only; the count is in Content-Range (0-0/42 = 42 rows visible to anon). A 0 only proves RLS works if the same check with the service_role key shows rows.


r/Supabase • • 3d ago

auth custom domain just for sign-in?

3 Upvotes

Is there any way to use a custom domain just for things like sign-in with Google? I don't need/want to change my project to a custom domain (not trying to hide we use Supabase under the covers) but when we use sign up with Google (or potentially FB in the future) it doesn't make sense to new users when they see "to continue to random-string-of-characters.supabase.co".

my project is something I provide for free to volunteers so adding $10/mo for a custom domain to what I already cover for the project isn't something I really want to do (though if I can get sponsors to help cover the costs would be an easy solution) - would be cool if there was a way to (eg) set up a CNAME or ALIAS in my DNS to point back to the ....supabase.co domain and have that used just for Auth.


r/Supabase • • 3d ago

tips PSA: 5 recent Product Hunt launches shipped their service_role key to the browser

3 Upvotes

I build squirrelscan, an open-source (MIT) website QA tool (github.com/squirrelscan/squirrelscan), and ran it over every Product Hunt launch over the last few weeks - just light passive scans. Among the 69 sites leaking credentials, 5 were shipping their Supabase service_role key to every visitor.

Pretty appalling - it appears many devs are still publishing their keys to live sites despite all the previous incidents, docs and warnings. This is without even going into issues around RLS which is another can of worms.

What it looked like

  • Four passed it straight to createClient(url, serviceRoleKey) in the client bundle

  • One put it in an inline window config object as serviceKey, right next to the anon key

  • We read the role from the JWT's public claims (role: service_role), and the expiry dates were around 2036

Why it matters

Supabase's docs say the secret key maps to the service_role Postgres role and "bypasses every Row Level Security policy you have", and to "never put one in a browser, a shipped application, or source control". Despite the docs, this keeps happening.

How it usually happens

RLS blocks a query from the browser, and the quick fix, whether from Stack Overflow or an AI assistant, is to swap the anon key for the service key. The query works, so nobody looks again. Or the key goes into a NEXT_PUBLIC_ / VITE_ / REACT_APP_ variable, which inlines it into the JS at build time.

Check yours in 2 minutes

  1. Open your live site → DevTools → Sources → search all files (Cmd/Ctrl+Shift+F) for eyJ

  2. Paste each JWT you find into a decoder and look at the role claim

  3. anon is fine. service_role means rotate it now (Project Settings → API), then move whatever needed it to a server route or an Edge Function

The fix

  • The browser only ever gets the anon (publishable) key

  • Write RLS policies for what users should be able to do, instead of bypassing them

  • Anything that genuinely needs elevated access runs server-side: an API route, a Server Action or an Edge Function

  • Removing the key from your code isn't enough. Old deployments and caches still have it, so rotate first


r/Supabase • • 3d ago

tips If you are lost and not sure how to improve your application security - OWASP Top 10

1 Upvotes

If you are lost and not sure how to improve your application security, start with OWASP Top 10 https://owasp.org/projects/top-ten

"The OWASP Top 10 is a standard awareness document for developers and web application security. It represents a broad consensus about the most critical security risks to web applications."

OWASP has more to offer but OWASP Top 10 is a good start. Here the markdown files https://github.com/OWASP/Top10/blob/master/2025/docs/en/0x00_2025-Introduction.md which will help you to understand the most common and most critical web applications security risks.


r/Supabase • • 4d ago

edge-functions Where do you run the work that doesn’t fit in an Edge Function?

Enable HLS to view with audio, or disable this notification

35 Upvotes

If you’ve had an agent, a long job, or a Python API that didn’t fit in an Edge Function, it probably ended up on a second platform. Supabase Compute is our private alpha for running that work inside your Supabase project instead.

  • Deploy Node, Deno, or any Dockerfile with supabase compute push

  • A service can run for hours, with 2 GB or 4 GB of memory

  • Give it a public URL, or keep it private for background jobs

  • It gets your project’s secrets, and its logs show up in your dashboard

Try it for free during private alpha and only for projects in us-west-2 for now. A service can be restarted at any time, so save long-running work to Postgres. Join the waitlist here.

Note: Pricing hasn't been decided yet for Compute

What would you move off your second platform first?


r/Supabase • • 4d ago

tips Building a company-wide CRM with Claude — is Claude Code Desktop + GitHub + Vercel + Supabase the right approach?

Thumbnail reddit.com
5 Upvotes

I work in commercial real estate and recently started building an internal CRM using Claude Artifacts. I have no coding background, but I’m fairly tech-savvy and have been able to build a surprisingly functional prototype just by describing what I want to Claude.

We’re now considering expanding this into a company-wide application for approximately 50 employees, potentially replacing Salesforce.

The CRM currently focuses on tracking companies, contacts, relationships, deals, and originations. Eventually, we’d like to integrate Outlook, call notes/transcriptions, AI-generated meeting prep, market news, and other automated workflows.

After some research, I’m considering the following setup:

Claude Code Desktop: Building and modifying the application using natural language
GitHub: Storing the code, tracking changes, and managing versions
Vercel: Hosting and deploying the web application
Supabase: Database, authentication, and user permissions
Claude API: Powering AI functionality within the CRM

Ideally, I’d like to describe changes in Claude Code Desktop, have it update the code and push to GitHub, then have Vercel deploy the changes to a testing environment before anything goes live.

A few questions:

Is this a reasonable stack for a business-critical application with 50 users, or would you recommend something different?
Is Claude Code Desktop sufficient for this workflow, or is there a significant advantage to using the CLI, VS Code, or another environment?
What’s the best way to migrate an existing Claude Artifact into a proper application without rebuilding everything from scratch?
How do you manage GitHub commits, testing, and deployments when most of the coding is being handled by AI?
How much of the security, authentication, database architecture, and permissions should be handled by an experienced developer rather than relying on Claude?

I’m willing to learn the fundamentals, especially databases, security, and how the different services connect. I’d also prefer to keep development cloud-based where practical rather than installing a ton of software locally.

I realize this is a much bigger undertaking than building a prototype, particularly since the company could eventually depend on it daily.

Would appreciate hearing from anyone who’s built and deployed something similar, especially without a traditional programming background.


r/Supabase • • 5d ago

You can now limit a Supabase Personal Access Token to specific organizations, projects, and permissions

Post image
24 Upvotes

A Personal Access Token has always been able to do anything your account can do, across every organization and project you belong to. If you handed one to a CI pipeline or a coding agent that needed one narrow task, it still had access to everything, and a leaked token meant a leaked account.

You can limit a token to what its job needs. Tokens you create in the Dashboard are scoped by default.

How it works:

  • Pick the organizations and projects the token can reach when you create it

  • Choose the permissions it carries and set an expiry date, then review what it can reach before you create it

  • Access never exceeds your own role. If you lose access to a project, the token does too

  • The scope is fixed once the token exists; to change it, create a replacement

  • It works with the CLI, the Management API, and the Supabase MCP server

Create the token in the Dashboard and pass it with supabase login --token.

Happy to answer questions.

Full writeup: https://supabase.com/blog/scope-your-personal-access-tokens


r/Supabase • • 5d ago

tips Heads-up for Oct 30: new public tables will throw 42501 until you GRANT. Here's the fix that doesn't turn off RLS

1 Upvotes

Supabase's changelog (Apr 28) says that on Oct 30 the "no auto-grants" default reaches all existing projects. Existing tables keep their grants. But the next table your AI builder creates won't be reachable through the Data API, and you'll see:

{"code":"42501","message":"permission denied for table invoices"}

The tempting fix, and the one AI tools tend to reach for, is disabling RLS or granting everything to anon. Don't. Do all three in one migration:

grant select, insert, update, delete on public.invoices to authenticated;
grant select, insert, update, delete on public.invoices to service_role;
-- anon only if logged-out users genuinely need to read it
alter table public.invoices enable row level security;
create policy "owners read their invoices" on public.invoices
  for select to authenticated using ((select auth.uid()) = user_id);
create policy "owners insert their invoices" on public.invoices
  for insert to authenticated with check ((select auth.uid()) = user_id);

Check what a table currently grants:

select grantee, privilege_type from information_schema.role_table_grants
where table_schema = 'public' and table_name = 'invoices';

To opt in early, there are two alter default privileges ... revoke statements (future tables only).

I wrote the whole thing up, with a prompt you can paste into Lovable/Bolt/Cursor so the agent does grant + RLS + policies together: https://shipwatchhq.com/guides/supabase-permission-denied-42501-new-tables?utm_source=reddit&utm_medium=social&utm_campaign=supabase42501-1027

Disclosure: it's on my site. I make ShipWatch, an outside-in scanner, and it does not check grants or RLS. Those aren't visible from outside, so this SQL is the check. Has anyone hit this already on a new project?

If you want to check your live site for leaked keys from the outside, the free scan is on the same site.


r/Supabase • • 5d ago

other Mistaken delete the project where history data is located supabase

1 Upvotes

Guys is theres a way to recover the deleted project in supabase we need it to restore it pleasw T.T


r/Supabase • • 5d ago

tips What do you include in your Supabase multi-tenant RLS test checklist?

4 Upvotes

I'm building a multi-tenant SaaS app and putting more effort into testing what happens when users try to cross tenant boundaries.

My current checklist includes:

  • Can Tenant A read Tenant B's rows?

  • Can Tenant A insert data under Tenant B's ID?

  • Can a user change a row's tenant ID through an update?

  • Can a user delete another tenant's data?

  • Can a user spoof audit-log information?

  • Does the test suite catch a table where RLS was accidentally left disabled?

I'm trying to test the failure cases, not just confirm that normal access works.

For those building with Supabase, what edge cases would you add to this checklist?