On April 21, we are restricting certain SQL actions you can perform in your database’s auth, storage, and realtime schemas.
Why are we making these restrictions?#
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.
What this means for your project#
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_migrationsstorage.migrationsrealtime.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, andrealtimeschemas - Create RLS policies and database triggers on the following tables:
auth.audit_log_entriesauth.identitiesauth.refresh_tokensauth.sessionsauth.usersstorage.bucketsstorage.migrationsstorage.objectsstorage.s3_multipart_uploadsstorage.s3_multipart_uploads_partsrealtime.messages
How to determine if you’re affected?#
- Run the following query to check if you created any tables in the
auth,storage, andrealtimeschemas:
_14SET search_path = '';_14SELECT oid::regclass AS table_name_14FROM pg_class _14WHERE _14 (relnamespace = 'auth'::regnamespace AND relowner != 'supabase_auth_admin'::regrole) _14 OR (relnamespace = 'storage'::regnamespace AND relowner != 'supabase_storage_admin'::regrole) _14 OR ( _14 relnamespace = 'realtime'::regnamespace_14 AND relowner NOT IN ( _14 SELECT oid _14 FROM pg_roles _14 WHERE rolname IN ('supabase_admin', 'supabase_realtime_admin') _14 ) _14 );
- Run the following query to check if you created any database functions in the
auth,storage, andrealtimeschemas:
_14SET search_path = '';_14SELECT pg_catalog.format('%s(%s)', oid::regproc, pg_get_function_identity_arguments(oid::regproc)) AS function_name_14FROM pg_proc _14WHERE _14 (pronamespace = 'auth'::regnamespace AND proowner != 'supabase_auth_admin'::regrole) _14 OR (pronamespace = 'storage'::regnamespace AND proowner != 'supabase_storage_admin'::regrole) _14 OR ( _14 pronamespace = 'realtime'::regnamespace _14 AND proowner NOT IN ( _14 SELECT oid _14 FROM pg_roles _14 WHERE rolname IN ('supabase_admin', 'supabase_realtime_admin') _14 ) _14 );
What you need to do#
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:
_10-- ..._10CREATE TABLE auth.my_custom_table (_10 -- id int8 ..._10);_10-- ...
Then you need to edit it locally into:
_10-- ..._10CREATE SCHEMA IF NOT EXISTS my_custom_schema;_10CREATE TABLE my_custom_schema.my_custom_table (_10 -- id int8 ..._10);_10-- ...
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