What if your app could prevent data mix-ups even when everyone is changing things at once?
Why Transaction basics in Firebase? - Purpose & Use Cases
Imagine you are updating a shared shopping list with your friends. You try to add an item while your friend is removing another. Without a clear way to manage these changes, the list can get mixed up or lose some items.
Doing these updates by hand means you might overwrite each other's changes or end up with wrong data. It's slow because you have to check and fix mistakes, and it's easy to lose track of who changed what.
Transactions let you bundle multiple changes together so they happen all at once or not at all. This keeps your data safe and consistent, even when many people update it at the same time.
read data modify data write data
runTransaction(async (transaction) => {
const doc = await transaction.get(docRef);
const data = doc.data();
transaction.update(docRef, newData);
})It makes sure your data stays correct and reliable, no matter how many people are changing it at once.
When two friends try to book the last seat on a bus at the same time, transactions ensure only one booking succeeds, preventing double reservations.
Manual updates can cause data conflicts and errors.
Transactions group changes to keep data safe and consistent.
This helps apps handle many users updating data simultaneously without mistakes.
Practice
Solution
Step 1: Understand transaction purpose
Transactions are designed to keep data changes safe and consistent when multiple users might update the same data.Step 2: Eliminate unrelated options
Speeding up retrieval, storing files, or sending notifications are not the main goals of transactions.Final Answer:
To ensure data changes are safe and consistent -> Option BQuick Check:
Transaction purpose = safe and consistent data [OK]
- Thinking transactions speed up data retrieval
- Confusing transactions with file storage
- Assuming transactions send notifications
Solution
Step 1: Recall Firebase transaction syntax
The correct method to start a transaction is callingtransaction()on a database reference.Step 2: Check each option
database.ref('path').transaction(updateFunction) usesref('path').transaction(updateFunction), which is correct. Options A, B, and D use incorrect method names or call patterns.Final Answer:
database.ref('path').transaction(updateFunction) -> Option AQuick Check:
Correct method is .transaction() on ref [OK]
- Using .setTransaction() which does not exist
- Calling transaction directly on database object
- Using .runTransaction() which is invalid
database.ref('counter').transaction(currentValue => {
if (currentValue === null) {
return 1;
} else {
return currentValue + 1;
}
});
What will be the value of 'counter' after this transaction if it was initially 5?Solution
Step 1: Analyze the transaction function logic
The function checks if the current value is null; if so, it returns 1. Otherwise, it returns currentValue + 1.Step 2: Apply initial value 5
Since currentValue is 5 (not null), the function returns 5 + 1 = 6.Final Answer:
6 -> Option AQuick Check:
5 + 1 = 6 [OK]
- Assuming value stays the same
- Confusing null check logic
- Returning 1 regardless of current value
database.ref('score').transaction(() => {
database.ref('score').set(10);
return 20;
});Solution
Step 1: Understand transaction function rules
All reads must happen before any writes inside the transaction function to ensure consistency.Step 2: Identify the problem in code
The code callsset(10)inside the transaction function before returning a new value, which violates the rule.Final Answer:
Reads must happen before writes inside the transaction function -> Option CQuick Check:
Transaction rule: read before write [OK]
- Calling set() inside transaction function
- Returning a value is allowed and required
- Thinking transaction function must be async
database.ref('users/user1/points').transaction(currentPoints => {
// Your code here
});Solution
Step 1: Understand the condition to increment points
Points should increment only if currentPoints is less than 100 or if it is null (no points yet).Step 2: Check each option logic
if (currentPoints === null || currentPoints < 100) { return (currentPoints || 0) + 1; } else { return currentPoints; } increments points by 1 if currentPoints is null or less than 100, else returns currentPoints unchanged. This matches the requirement. if (currentPoints >= 100) { return currentPoints + 1; } else { return currentPoints; } increments when points are 100 or more, which is wrong. return currentPoints + 1; always increments ignoring the limit. if (currentPoints === null) { return 0; } else { return 100; } resets points incorrectly.Final Answer:
if (currentPoints === null || currentPoints < 100) { return (currentPoints || 0) + 1; } else { return currentPoints; } -> Option DQuick Check:
Increment only if points < 100 or null [OK]
- Incrementing points when already 100 or more
- Ignoring null initial value
- Resetting points instead of incrementing
Ready to prove it?
Pass the test and this pattern moves unknown
