83 83. Step 9: Set Up Supabase Database
As of Oct 22, 2026 · Official docs: Supabase: Database migrations · supabase db push
Your project ships with migrations: SQL files in supabase/migrations that define the whole database. One command sends them to your Supabase project. They create the tables (profiles, tasks, usage tracking), the security rules, the task-attachments storage bucket for images, and the connection to Stripe.
83.1 Run Database Migrations
Do this after the Supabase CLI is logged in and linked to your project (Step 5a). In Classes 10–12, this is (G) Create the database, after the Supabase, Google, OpenAI and Stripe setup.
Work in the
task-appfolder, the project root (wheresupabase/config.tomllives).Claude runs this command in the terminal for you, after asking your permission. (To run it yourself, type it in VS Code’s terminal and press
Enter.)npx supabase db pushnpx supabaseruns the Supabase CLI, anddb pushmeans “send my database changes up to my Supabase project” (dbfor database,pushfor upload). It applies every migration that your project doesn’t have yet.
There is a bug in the current code. When running the above command you will probably see the following errors.
$ npx supabase db push
Initialising login role...
Connecting to remote database...
Do you want to push these migrations to the remote database?
• 0_init_profile.sql
• 1_init_tasks.sql
• 2_init_auth.sql
• 3_init_storage_schema.sql
• 4_init_usage_tracking.sql
• 5_init_task_limit_triggers.sql
• 6_init_account_tier_triggers.sql
• 7_init_stripe_integration.sql
[Y/n] y
Applying migration 0_init_profile.sql...
NOTICE (42710): extension "uuid-ossp" already exists, skipping
Applying migration 1_init_tasks.sql...
ERROR: function uuid_generate_v4() does not exist (SQLSTATE 42883)
At statement: 0
-- Tasks table
create table public.tasks (
task_id uuid default uuid_generate_v4() primary key,
^
Try rerunning the command with --debug to troubleshoot the error.
This is caused by the file: supabase/migrations/1_init_tasks.sql
The file contains a call to the function uuid_generate_v4(), which comes from the uuid-ossp extension. On Supabase, that extension is already installed (that’s what the NOTICE above says), but in a separate schema (a folder of database objects) named extensions. The migration calls the function without that schema name, and while db push runs it, the database doesn’t look in extensions, so it reports that the function does not exist.
The simplest fix: in supabase/migrations/1_init_tasks.sql, replace uuid_generate_v4() with gen_random_uuid(). That function is built into PostgreSQL itself (no extension needed) and also creates a random ID. (Writing the full name, extensions.uuid_generate_v4(), would also work.) Save the file and try the npx supabase db push again.
- Wait for the migrations to complete without errors.
- In the Supabase dashboard, open Table Editor to confirm the tables exist, and Storage to confirm the
task-attachmentsbucket exists.
83.2 Enable Row Level Security (RLS)
The migrations turn on RLS for the profiles, tasks and usage_tracking tables and define these policies:
tasks: a signed-in user can read, create, change and delete only the rows whoseuser_idis their own user ID.profiles: a signed-in user can only read their own profile. There is no policy that lets users create, change or delete profiles. (There are two read policies, “Users can read own profile” and “Users can read own Stripe data”, but both allow the same thing.) A trigger creates the profile when someone signs up, and the Stripe Edge Function changes the subscription plan after a payment.usage_tracking: a signed-in user can only read their own rows. A trigger updates the counts when a task is created.- Visitors who aren’t signed in can’t read or change any of these tables, because no policy allows it.
- Code that uses the Supabase secret key without a signed-in user’s token (like the Stripe Edge Function) bypasses RLS completely.
The storage bucket task-attachments has its own policies: anyone can view the files, but only signed-in users can upload or delete files, and only in their own folder.
Each policy is a create policy statement in the migration files (2_init_auth.sql, 3_init_storage_schema.sql, 4_init_usage_tracking.sql and 7_init_stripe_integration.sql), so you can read them there. The Supabase dashboard also has a Policies page that lists them.
Practice Questions
Easy
Question 1 · Short answer
What is a database migration?
Question 2 · Write the command
Write the command that sends the project’s migrations to your remote Supabase database.
Question 3 · Short answer
According to the page, which folder should you be in when you run that command, and why?
Question 4 · True or false
Row Level Security (RLS) lets the database decide, row by row, which data each user may read or change.
Question 5 · Multiple choice
Which of these does npx supabase db push not create in your Supabase project?
- The
profiles,tasksandusage_trackingtables - The security rules (RLS policies) for those tables
- The
task-attachmentsstorage bucket for task images - Your Supabase project’s publishable and secret API keys
Medium
Question 6 · Predict the output
db push lists eight migrations, from 0_init_profile.sql to 7_init_stripe_integration.sql. Which one is applied first, and why does the order matter?
Question 7 · Short answer
During db push you see:
NOTICE (42710): extension "uuid-ossp" already exists, skipping
Is this an error that you need to fix?
Question 8 · Find the bug
The push stops with:
ERROR: function uuid_generate_v4() does not exist (SQLSTATE 42883)
Which file do you change, what do you change, and what do you do next?
Question 9 · Short answer
How can you check that the migrations worked?
Question 10 · Matching
Match each kind of access with what the RLS policies described on this page allow.
| Who | What the policies allow | |
|---|---|---|
| 1. A signed-in user | A. Bypasses RLS completely | |
| 2. A visitor who isn’t signed in | B. Can read, create, change and delete their own tasks, but can only read their own profile | |
| 3. Code that uses the Supabase secret key, without a user’s token | C. Can’t read or change the profiles, tasks or usage_tracking tables |
Hard
Question 11 · Scenario
After fixing 1_init_tasks.sql, you run npx supabase db push again. Will 0_init_profile.sql be applied a second time? Explain.
Question 12 · Long answer
Why do projects define their database with migration files instead of having each developer create the tables by clicking around in the Supabase dashboard? Give at least two reasons.
Question 13 · Scenario
Imagine the migrations had created the tasks table but forgot to turn on RLS for it. What risk would that create for task-app’s users?