On April 21, we are restricting certain SQL actions you can perform in your database’s auth, storage, and realtime schemas.
Supabase Auth, Storage, and Realtime services each rely on their respective schemas in order to function properly.
These restrictions prevent unintended side effects like third-party tooling and user defined changes altering schemas or their objects, such as migration tables and database functions, that could disrupt or break functionality.
On April 21, you will no longer be able to perform the following actions on the auth, storage, and realtime schemas:
- Create tables and database functions
- Drop existing tables or database functions
- Create indexes on existing tables
- Perform destructive actions (i.e.
INSERT, UPDATE, DELETE, TRUNCATE) on the following migration tables:
auth.schema_migrations
storage.migrations
realtime.schema_migrations
- Revoking privileges on tables in these schemas from API roles (e.g.
anon)
However, you will still have permissions to perform the following actions:
- Create foreign keys referencing tables in the
auth, storage, and realtime schemas
- Create RLS policies and database triggers on the following tables:
auth.audit_log_entries
auth.identities
auth.refresh_tokens
auth.sessions
auth.users
storage.buckets
storage.migrations
storage.objects
storage.s3_multipart_uploads
storage.s3_multipart_uploads_parts
realtime.messages
- Run the following query to check if you created any tables in the
auth, storage, and realtime schemas:
_14SELECT oid::regclass AS table_name
_14 (relnamespace = 'auth'::regnamespace AND relowner != 'supabase_auth_admin'::regrole)
_14 OR (relnamespace = 'storage'::regnamespace AND relowner != 'supabase_storage_admin'::regrole)
_14 relnamespace = 'realtime'::regnamespace
_14 AND relowner NOT IN (
_14 WHERE rolname IN ('supabase_admin', 'supabase_realtime_admin')
- Run the following query to check if you created any database functions in the
auth, storage, and realtime schemas:
_14SELECT pg_catalog.format('%s(%s)', oid::regproc, pg_get_function_identity_arguments(oid::regproc)) AS function_name
_14 (pronamespace = 'auth'::regnamespace AND proowner != 'supabase_auth_admin'::regrole)
_14 OR (pronamespace = 'storage'::regnamespace AND proowner != 'supabase_storage_admin'::regrole)
_14 pronamespace = 'realtime'::regnamespace
_14 AND proowner NOT IN (
_14 WHERE rolname IN ('supabase_admin', 'supabase_realtime_admin')
If any of the above queries return a result, you must move them to either the public schema or a schema that you’ve created. Otherwise, they will be deleted.
- Here’s how you can move a table to another schema:
_10CREATE SCHEMA IF NOT EXISTS my_custom_schema;
_10ALTER TABLE storage.my_custom_table SET SCHEMA my_custom_schema;
- Here’s how you can move a database function to another schema:
_10CREATE SCHEMA IF NOT EXISTS my_custom_schema;
_10ALTER FUNCTION storage.custom_function() SET SCHEMA my_custom_schema;
Additionally, if you're using Migrations or Branching, you'll need to patch your migrations to move these objects to your own schemas. E.g. if you have a migration 20250101000000_add_custom_table.sql like so:
_10CREATE TABLE auth.my_custom_table (
Then you need to edit it locally into:
_10CREATE SCHEMA IF NOT EXISTS my_custom_schema;
_10CREATE TABLE my_custom_schema.my_custom_table (
Then you'll need to repair the migration history on the linked project:
_10supabase migration repair --status reverted 20250101000000
_10supabase migration repair --status applied 20250101000000