Testing RLS policies in Supabase - Time & Space Complexity
When testing Row Level Security (RLS) policies in Supabase, we want to know how the time to check access grows as we test more users or rows.
We ask: How does the number of policy checks or queries change when we increase the data or users?
Analyze the time complexity of the following operation sequence.
// For each user, test access to rows
for (const userId of userIds) {
const { data, error } = await supabase
.from('items')
.select('*')
.eq('owner_id', userId)
}
This code tests RLS by querying all rows owned by each user one by one.
Identify the API calls, resource provisioning, data transfers that repeat.
- Primary operation: Database query to fetch rows for one user.
- How many times: Once per user in the userIds list.
Each additional user adds one more query to test their access.
| Input Size (n) | Approx. Api Calls/Operations |
|---|---|
| 10 users | 10 queries |
| 100 users | 100 queries |
| 1000 users | 1000 queries |
Pattern observation: The number of queries grows directly with the number of users tested.
Time Complexity: O(n)
This means the time to test RLS policies grows linearly as you test more users.
[X] Wrong: "Testing RLS for multiple users is just one query regardless of user count."
[OK] Correct: Each user requires a separate query to check their access, so queries add up with more users.
Understanding how testing scales helps you design efficient checks and shows you grasp how cloud services handle multiple requests.
"What if we batch all user IDs into one query with an 'IN' filter? How would the time complexity change?"
Practice
Solution
Step 1: Understand RLS purpose
RLS policies restrict access to rows based on user identity or conditions.Step 2: Compare options
Only To control which rows a user can access or modify in a table describes controlling access to rows per user, which is the core of RLS.Final Answer:
To control which rows a user can access or modify in a table -> Option DQuick Check:
RLS controls row access = A [OK]
- Confusing RLS with indexing or encryption
- Thinking RLS handles backups
- Assuming RLS speeds up queries
profiles in Supabase?Solution
Step 1: Recall correct syntax for enabling RLS
The correct SQL command isALTER TABLE table_name ENABLE ROW LEVEL SECURITY;.Step 2: Match options with syntax
Only ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; matches the exact syntax supported by Supabase/PostgreSQL.Final Answer:
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; -> Option AQuick Check:
Enable RLS syntax = A [OK]
- Using 'RLS' shorthand incorrectly
- Using underscores incorrectly
- Using SET instead of ENABLE
messages table:CREATE POLICY "Users can view their messages" ON messages FOR SELECT USING (user_id = auth.uid());
What will happen if user with
auth.uid() = '123' runs SELECT * FROM messages;?Solution
Step 1: Understand the policy condition
The policy allows SELECT only ifuser_id = auth.uid(). For user '123', only rows with user_id '123' are visible.Step 2: Predict query result
The SELECT query returns only messages owned by user '123'. No syntax errors occur.Final Answer:
They will see only messages where user_id = '123' -> Option BQuick Check:
Policy filters rows by user_id = auth.uid() = B [OK]
- Assuming all rows are visible
- Thinking policy blocks all rows
- Confusing syntax error with policy effect
CREATE POLICY "Allow updates" ON profiles FOR UPDATE USING (user_id = auth.uid());
But users report they cannot update their profiles. What is the likely problem?
Solution
Step 1: Understand difference between USING and WITH CHECK
USING controls which rows can be selected or updated; WITH CHECK controls which updated rows are allowed after update.Step 2: Identify update permission issue
For UPDATE, WITH CHECK is needed to allow the new row values. Using only USING blocks updates even if row is accessible.Step 3: Check other options
RLS must be enabled, but question implies it is. auth.uid() returning NULL is unlikely if user is logged in. Policy name is valid.Final Answer:
The policy should use WITH CHECK instead of USING -> Option CQuick Check:
Update policies need WITH CHECK = A [OK]
- Using only USING clause for updates
- Forgetting to enable RLS
- Assuming policy name affects behavior
orders table correctly restricts users to only see their own orders. Which approach is best to verify this?Solution
Step 1: Understand testing RLS requires simulating user access
Testing RLS means running queries as different users to see if access is limited correctly.Step 2: Evaluate options
RunSELECT * FROM orders;as different authenticated users and check results runs queries as different users, which tests the policy effectively. Disable RLS temporarily and check if all orders are visible disables RLS, which doesn't test policy. Check the policy text only without running queries only reads policy text, no test. RunSELECT * FROM orders;as the database admin user uses admin user who bypasses RLS.Final Answer:
RunSELECT * FROM orders;as different authenticated users and check results -> Option AQuick Check:
Test RLS by querying as different users = D [OK]
- Testing only as admin user
- Disabling RLS to test policies
- Not running actual queries
Ready to prove it?
Pass the test and this pattern moves unknown
