Common rule patterns in Firebase - Time & Space Complexity
When using Firebase security rules, it's important to know how the number of checks grows as your data or requests grow.
We want to understand how the time to evaluate rules changes when more data or requests are involved.
Analyze the time complexity of these Firebase rules checking multiple documents.
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if request.auth != null &&
exists(/databases/$(database)/documents/users/$(request.auth.uid)) &&
get(/databases/$(database)/documents/posts/$(postId)).data.published == true;
}
}
}
These rules check if the user exists and if the post is published before allowing read access.
Look at what happens each time a read request is made:
- Primary operation: Two document reads: one to check the user document, one to check the post document.
- How many times: Once per read request for each post.
As the number of read requests grows, the number of document reads grows the same way.
| Input Size (n) | Approx. Api Calls/Operations |
|---|---|
| 10 | 20 document reads (2 per request) |
| 100 | 200 document reads |
| 1000 | 2000 document reads |
Pattern observation: The number of operations grows directly with the number of requests.
Time Complexity: O(n)
This means the time to check rules grows linearly with the number of read requests.
[X] Wrong: "Checking multiple documents in rules happens all at once and does not add time."
[OK] Correct: Each document read in rules is a separate operation, so more checks mean more time.
Understanding how rule checks scale helps you design efficient security rules that keep your app fast and safe.
What if we added a loop in rules to check multiple related documents? How would the time complexity change?
Practice
Solution
Step 1: Understand Firebase security rules role
Firebase security rules define who can access or change data in your database.Step 2: Identify the main function
The main function is to control read and write access to protect data.Final Answer:
To control who can read or write data -> Option AQuick Check:
Security rules = access control [OK]
- Confusing rules with data backup
- Thinking rules speed up queries
- Assuming rules store passwords
Solution
Step 1: Identify correct Firebase auth syntax
Firebase usesrequest.authto check if a user is authenticated.Step 2: Match syntax to allow read only if authenticated
The correct condition isrequest.auth != nullmeaning user is logged in.Final Answer:
allow read: if request.auth != null; -> Option AQuick Check:
request.auth != null means user logged in [OK]
- Using incorrect variable names like user.loggedIn
- Checking auth.user instead of request.auth
- Confusing request.user with request.auth
allow write: if request.auth.uid == resource.data.ownerId;
What does this rule enforce?
Solution
Step 1: Understand the condition in the rule
The rule checks if the user's ID matches the ownerId stored in the data.Step 2: Interpret the effect of the condition
This means only the user who owns the data (ownerId) can write to it.Final Answer:
Only the owner of the data can write to it -> Option BQuick Check:
request.auth.uid == resource.data.ownerId means owner only [OK]
- Assuming all authenticated users can write
- Thinking admins are required
- Believing no one can write
allow read: if request.auth.uid = resource.data.ownerId;
Solution
Step 1: Check the comparison operator used
The rule uses a single equals sign (=) which is assignment, not comparison.Step 2: Correct operator for comparison in Firebase rules
Firebase rules require double equals (==) to compare values.Final Answer:
Using single equals (=) instead of double equals (==) for comparison -> Option CQuick Check:
Use == for comparison, not = [OK]
- Confusing assignment (=) with comparison (==)
- Thinking semicolon is mandatory
- Believing request.auth.uid is invalid
Solution
Step 1: Ensure user can update only their own profile
The rule must check that the authenticated user matches the existing userId in data.Step 2: Prevent changing the userId field
Check that the new data's userId matches the old data's userId to prevent changes.Final Answer:
allow update: if request.auth.uid == resource.data.userId && request.resource.data.userId == resource.data.userId; -> Option DQuick Check:
Match auth.uid and keep userId unchanged [OK]
- Allowing userId to be changed
- Not verifying user owns the profile
- Using != instead of == for ownership check
Ready to prove it?
Pass the test and this pattern moves unknown
