Firestore trigger functions in Firebase - Time & Space Complexity
When using Firestore trigger functions, it's important to understand how the time to run your function changes as your data grows.
We want to know how the number of operations grows when many documents trigger the function.
Analyze the time complexity of the following Firestore trigger function.
exports.onUserUpdate = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const newData = change.after.data();
const oldData = change.before.data();
if (newData.status !== oldData.status) {
return updateUserStats(context.params.userId);
}
return null;
});
function updateUserStats(userId) {
// Updates stats for the user
return admin.firestore().collection('stats').doc(userId).set({ updated: true });
}
This function triggers when a user document changes. It checks if the status changed, then updates stats for that user.
Look for repeated actions that affect performance.
- Primary operation: The function runs once per document update event.
- How many times: It runs once for each user document that changes.
As more user documents update, the function runs more times.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 function runs |
| 100 | 100 function runs |
| 1000 | 1000 function runs |
Pattern observation: The number of operations grows directly with the number of document updates.
Time Complexity: O(n)
This means the total work grows linearly with the number of document updates triggering the function.
[X] Wrong: "The function runs once and handles all document updates at once."
[OK] Correct: Each document update triggers the function separately, so the work adds up with more updates.
Understanding how trigger functions scale helps you design efficient backend processes that respond well as your app grows.
What if the function also queried a collection of related documents for each update? How would the time complexity change?
Practice
Solution
Step 1: Understand Firestore triggers
Firestore triggers are special functions that run automatically when data changes in Firestore.Step 2: Identify the trigger's purpose
They help keep your app reactive by running code on create, update, or delete events without manual calls.Final Answer:
Automatically runs code when data changes in Firestore -> Option DQuick Check:
Firestore triggers = automatic code run on data change [OK]
- Thinking triggers run manually
- Confusing triggers with database creation
- Assuming triggers delete data without events
Solution
Step 1: Recall Firestore trigger syntax
The correct syntax uses exports, functions.firestore.document(path).onCreate(handler).Step 2: Match syntax to options
exports.onCreate = functions.firestore.document('users/{userId}').onCreate((snap, context) => { }); matches this pattern exactly with document path and onCreate event.Final Answer:
exports.onCreate = functions.firestore.document('users/{userId}').onCreate((snap, context) => { }); -> Option BQuick Check:
Correct Firestore onCreate syntax = exports.onCreate = functions.firestore.document('users/{userId}').onCreate((snap, context) => { }); [OK]
- Missing exports keyword
- Using onCreate directly on firestore without document
- Wrong method name like create instead of onCreate
exports.logUpdate = functions.firestore.document('posts/{postId}').onUpdate((change, context) => {
const before = change.before.data();
const after = change.after.data();
console.log('Title before:', before.title);
console.log('Title after:', after.title);
});Solution
Step 1: Understand onUpdate trigger parameters
The onUpdate trigger receives a change object with before and after snapshots of the document.Step 2: Analyze the console logs
The code logs before.title and after.title, so both old and new titles are printed.Final Answer:
Logs the title before and after the update -> Option AQuick Check:
onUpdate logs before and after data [OK]
- Assuming only new data is available
- Thinking change.before is undefined
- Confusing onUpdate with onCreate
exports.deleteUser = functions.firestore.document('users/{userId}').onDelete((snap, context) => {
const userData = snap.data;
console.log('Deleted user:', userData.name);
});Solution
Step 1: Check how to access document data
Firestore document snapshot data is accessed by calling snap.data(), not snap.data property.Step 2: Identify the error in code
The code uses snap.data without parentheses, causing undefined userData and runtime error.Final Answer:
snap.data should be snap.data() to get document data -> Option CQuick Check:
Use snap.data() method to access document data [OK]
- Using snap.data instead of snap.data()
- Thinking onDelete can't use context parameter
- Assuming async is always required
Solution
Step 1: Choose the right trigger for updates
onUpdate triggers run on any document update, suitable for detecting changes.Step 2: Prevent infinite loops by checking field changes
Compare bio field before and after update; only proceed if bio changed to avoid recursive updates.Final Answer:
Use onUpdate trigger and compare change.before.data().bio with change.after.data().bio before updating -> Option AQuick Check:
Check field changes in onUpdate to avoid loops [OK]
- Using onWrite and updating unconditionally causing loops
- Using onCreate which triggers only once
- Not checking field changes before updating
Ready to prove it?
Pass the test and this pattern moves unknown
