Update and delete policies in Supabase - Time & Space Complexity
When using update and delete policies in Supabase, it's important to understand how the number of operations grows as data changes.
We want to know how the time to apply these policies changes when more rows are updated or deleted.
Analyze the time complexity of the following operation sequence.
// Update rows with policy check
const { data, error } = await supabase
.from('tasks')
.update({ status: 'done' })
.eq('user_id', currentUserId)
// Delete rows with policy check
const { data: delData, error: delError } = await supabase
.from('tasks')
.delete()
.eq('completed', true)
This sequence updates tasks for a user and deletes completed tasks, both subject to row-level policies.
Identify the API calls, resource provisioning, data transfers that repeat.
- Primary operation: Each update or delete request triggers a policy check on matching rows.
- How many times: The policy check runs once per affected row during update or delete.
As the number of rows to update or delete grows, the number of policy checks grows similarly.
| Input Size (n) | Approx. API Calls/Operations |
|---|---|
| 10 | 10 policy checks |
| 100 | 100 policy checks |
| 1000 | 1000 policy checks |
Pattern observation: The number of policy checks grows directly with the number of rows affected.
Time Complexity: O(n)
This means the time to apply update or delete policies grows linearly with the number of rows changed.
[X] Wrong: "Policies run once per request, so time stays the same no matter how many rows are updated or deleted."
[OK] Correct: Each row affected must be checked against the policy, so more rows mean more checks and longer time.
Understanding how policies affect operation time helps you design efficient database interactions and explain your reasoning clearly in discussions.
"What if we batch updates in smaller groups instead of one large update? How would the time complexity change?"
Practice
UPDATE policy in Supabase?Solution
Step 1: Understand the role of update policies
Update policies define who is allowed to modify existing rows in a table.Step 2: Differentiate from other policies
Read policies control reading, insert policies control adding data, and table creation is unrelated.Final Answer:
To control who can change existing data in a table -> Option CQuick Check:
Update policy = control data changes [OK]
- Confusing update with read or insert policies
- Thinking update policies control table creation
- Assuming update policies allow adding new rows
Solution
Step 1: Identify keywords for policy conditions
Supabase usesUSINGto specify who can perform an action andWITH CHECKto add extra conditions on updates.Step 2: Match keyword to extra conditions on update
WITH CHECKensures the new data meets certain rules before update is allowed.Final Answer:
WITH CHECK -> Option AQuick Check:
Extra update conditions = WITH CHECK [OK]
- Confusing USING and WITH CHECK keywords
- Thinking WHERE is used in policies
- Assuming ALLOW is a valid keyword
CREATE POLICY "Update own profile" ON profiles FOR UPDATE USING (auth.uid() = profiles.user_id) WITH CHECK (auth.uid() = profiles.user_id);
What happens if a user tries to update another user's profile?
Solution
Step 1: Understand USING condition role
TheUSINGclause controls who can perform the update. It checks if the user's ID matches the profile's user_id.Step 2: Check condition for updating another user's profile
If a user tries to update a different profile,auth.uid() = profiles.user_idis false, so update is denied.Final Answer:
The update is denied because USING condition fails -> Option DQuick Check:
USING controls update permission = denied if false [OK]
- Thinking WITH CHECK controls permission to update
- Assuming USING applies only to deletes
- Ignoring that both USING and WITH CHECK must pass
CREATE POLICY "Delete own posts" ON posts FOR DELETE USING (user_id = auth.uid());
But users report they cannot delete their posts. What is the likely problem?
Solution
Step 1: Check policy syntax
The policy syntax is correct for delete with USING condition matching user_id.Step 2: Consider RLS status
If Row Level Security (RLS) is not enabled on the table, policies have no effect and all actions are denied by default.Final Answer:
The policy might be missing enabling RLS on the table -> Option BQuick Check:
RLS must be enabled for policies to work [OK]
- Confusing USING and WITH CHECK for delete policies
- Forgetting to enable RLS on the table
- Thinking FOR UPDATE is needed for delete policies
Solution
Step 1: Understand USING vs WITH CHECK
USINGcontrols who can perform the update;WITH CHECKensures the new data meets conditions.Step 2: Apply condition on new data
The status check must apply to the new value after update, so usenew.status != 'shipped'inWITH CHECK.Step 3: Verify options
FOR UPDATE USING (auth.uid() = orders.user_id) WITH CHECK (new.status != 'shipped') correctly usesUSING (auth.uid() = orders.user_id)andWITH CHECK (new.status != 'shipped').Final Answer:
FOR UPDATE USING (auth.uid() = orders.user_id) WITH CHECK (new.status != 'shipped') -> Option AQuick Check:
Use WITH CHECK with new. for update conditions [OK]
- Checking old data instead of new data in WITH CHECK
- Putting status condition in USING instead of WITH CHECK
- Forgetting to use new. prefix for updated row
Ready to prove it?
Pass the test and this pattern moves unknown
