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 addedCommon 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('*')Reading progress
0% read
In this module
RLS
auth.uid()
Policy
USING clause
0%