Should you extend Supabase Auth with User Profiles?


Supabase Auth already has an Auth Users table.
The image might be blurry.
If you visit the project in your Supabase Account, you can check your Auth table of the project.
If you wanted to add additional data to your a User table, it's likely you've wondered 🤔
Should you create your own, separate profiles (or users) table in Supabase and link it with the Supabase Auth Users table?
OR
Should you extend the existing Supabase Auth Users table?
Supabase’s recommended pattern is to create a separate profiles (or users) table in the public schema rather than altering the built-in auth.users
table.
The auth.users
table (in the auth
schema) is managed internally and isn’t exposed via the auto-generated API.
Supabase maintainers explicitly advise
“It is not recommended to modify the schema of
auth.users
; the best way is to create a users (or profiles) table in the public schema and add any custom user-related data there.”
Linking Profiles to auth.users
Make your public.profiles
(or public.users
) table use the same UUID as primary key and reference auth.users(id)
-- Create profiles table
create table public.profiles (
id uuid primary key references auth.users(id) on delete cascade,
full_name text,
bio text,
avatar_url text
);
-- Enable RLS
alter table public.profiles enable row level security;
-- Policy for INSERT
create policy "Users can insert own profile"
on public.profiles for insert
with check (auth.uid() = id);
-- Policy for UPDATE
create policy "Users can update own profile"
on public.profiles for update
using (auth.uid() = id);
-- Policy for SELECT
create policy "Users can view own profile"
on public.profiles for select
using (auth.uid() = id);
Automatic Profile Creation on Signup
To automatically create a profile row when a new user signs up (via email or OAuth), use a Postgres trigger on auth.users
-- 1. Create the function
create or replace function public.handle_new_user()
returns trigger
language plpgsql security definer set search_path = public
as $$
begin
insert into public.profiles (id) values (NEW.id);
return NEW;
end;
$$;
-- 2. Create the trigger on the Supabase Auth table
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
Subscribe to my newsletter
Read articles from Mukesh Jaiswal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Mukesh Jaiswal
Mukesh Jaiswal
Driving business growth with AI Automation (as Business Automation Partner) | Helping startups build (as Software Developer)