JSTAcademy
0 XP
Dashboard
Crash Courses
Row Level Security
11 min
Masters+175 XP
Crash Courses · Masters

Row Level Security

Protect your data with PostgreSQL Row Level Security policies in Supabase.
11 min read+175 XP on completionCert: Supabase Crash Course
Tap any word in the text below to start reading from there.

Row Level Security

RLS is the security layer that makes Supabase safe to query directly from the browser. Without RLS, any user with your anon key can read all data.

Enable RLS

ALTER TABLE progress ENABLE ROW LEVEL SECURITY;
-- Now the table is locked — no access until policies are added

Common Policies

-- Users can only read their own progress
CREATE POLICY "Users can read own progress"
  ON progress FOR SELECT
  USING (user_id = auth.uid());

-- Users can insert their own progress
CREATE POLICY "Users can insert own progress"
  ON progress FOR INSERT
  WITH CHECK (user_id = auth.uid());

-- Users can update their own progress
CREATE POLICY "Users can update own progress"
  ON progress FOR UPDATE
  USING (user_id = auth.uid())
  WITH CHECK (user_id = auth.uid());

-- Courses are public (anyone can read)
CREATE POLICY "Courses are publicly readable"
  ON courses FOR SELECT
  USING (true);

Admin Policy

-- Only admins (role stored in profiles) can insert courses
CREATE POLICY "Admins can manage courses"
  ON courses FOR ALL
  USING (
    EXISTS (
      SELECT 1 FROM profiles
      WHERE id = auth.uid() AND role = 'admin'
    )
  );

Service Role Bypasses RLS

// Use service_role client to bypass RLS (admin operations)
import { createClient } from '@supabase/supabase-js'

const adminClient = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!  // server-only
)

// This ignores all RLS policies
const { data } = await adminClient
  .from('courses')
  .select('*')
0%