Skip to main content

Supabase Database

Supabase provides a full PostgreSQL database for storing your app’s data. Create tables, write queries, and let your data scale.

Prerequisites


Creating Tables

In Supabase Dashboard

  1. Go to Table Editor in sidebar
  2. Click Create a new table
  3. Name your table (e.g., tasks)
  4. Add columns

Via Nativeline

You can also ask Nativeline:
Create a Supabase table for tasks with:
- id (auto-generated UUID)
- user_id (links to auth users)
- title (text, required)
- is_completed (boolean, default false)
- created_at (timestamp, auto)

Common Column Types

TypeUse ForExample
uuidUnique IDsPrimary key, foreign keys
textStringsNames, descriptions
int4/int8NumbersCounts, quantities
boolTrue/falseIs completed, is active
timestamptzDates/timesCreated at, due date
jsonbComplex dataSettings, metadata
float8DecimalsPrices, coordinates

Example: Tasks Table

CREATE TABLE tasks (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES auth.users(id) NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  is_completed BOOLEAN DEFAULT false,
  due_date TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

Row Level Security (RLS)

Always enable RLS on tables with user data. Without it, anyone with your API key can read everything!

Enable RLS

  1. Table Editor → Select table
  2. Toggle “RLS” to enabled
  3. Add policies

Common Policies

Users see only their data:
CREATE POLICY "Users view own tasks"
ON tasks FOR SELECT
USING (auth.uid() = user_id);
Users create own data:
CREATE POLICY "Users create own tasks"
ON tasks FOR INSERT
WITH CHECK (auth.uid() = user_id);
Users update own data:
CREATE POLICY "Users update own tasks"
ON tasks FOR UPDATE
USING (auth.uid() = user_id);
Users delete own data:
CREATE POLICY "Users delete own tasks"
ON tasks FOR DELETE
USING (auth.uid() = user_id);

CRUD Operations

Create (Insert)

Add a function to create a new task with the given title.
Save it to Supabase with the current user's ID.

Read (Select)

Load all tasks for the current user from Supabase.
Order them by created_at, newest first.

Update

Add a function to mark a task as complete.
Update the is_completed field in Supabase.

Delete

Add a function to delete a task from Supabase.
Show confirmation before deleting.

Querying Data

Basic Queries

// All tasks for current user (handled by RLS)
let tasks = try await supabase
  .from("tasks")
  .select()
  .execute()

// Filter by completion status
let incomplete = try await supabase
  .from("tasks")
  .select()
  .eq("is_completed", value: false)
  .execute()

// Order by date
let ordered = try await supabase
  .from("tasks")
  .select()
  .order("due_date", ascending: true)
  .execute()

Filtering Options

MethodUseExample
.eq()Equalseq("status", "active")
.neq()Not equalsneq("status", "deleted")
.gt()Greater thangt("price", 100)
.lt()Less thanlt("age", 30)
.gte()Greater or equalgte("rating", 4)
.like()Pattern matchlike("name", "%John%")
.in()In arrayin("status", ["active", "pending"])
.is()Is null/boolis("deleted_at", nil)

Relationships

One-to-Many

Tasks belong to a category:
CREATE TABLE categories (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES auth.users(id),
  name TEXT NOT NULL
);

CREATE TABLE tasks (
  ...
  category_id UUID REFERENCES categories(id),
  ...
);

Querying with Relationships

// Get tasks with category names
let tasks = try await supabase
  .from("tasks")
  .select("*, categories(name)")
  .execute()

Handling Errors

Common Database Errors

ErrorCauseSolution
RLS policy violationNo matching policyCheck your policies
Foreign key violationReferenced row missingEnsure referenced data exists
Not null violationRequired field emptyProvide all required fields
Unique violationDuplicate valueCheck for existing records

Error Handling in App

Handle database errors gracefully:
- Show user-friendly error messages
- Log detailed errors for debugging
- Retry on network errors

Performance Tips

If you often query by a column (like user_id), add an index:
CREATE INDEX tasks_user_id_idx ON tasks(user_id);
Instead of select("*"), specify columns:
.select("id, title, is_completed")
.range(from: 0, to: 19) // First 20 items
Store frequently-accessed data locally and sync with Supabase.

Testing Database Operations

In Supabase Dashboard

  1. Table Editor → Select table
  2. View, add, edit, delete rows manually
  3. Great for testing and debugging

Via SQL Editor

  1. SQL Editor in Supabase sidebar
  2. Write and run queries directly
  3. Test policies and queries

Next Steps