📖 Scenario: You are building a simple inventory system using Firebase Realtime Database. You want to safely update the stock count of a product only if the current stock is enough to fulfill an order.
🎯 Goal: Build a Firebase transaction that reads the current stock of a product, checks if there is enough stock, and if yes, reduces the stock by the order quantity.
📋 What You'll Learn
Create a reference to the product stock in Firebase Realtime Database
Set an order quantity variable
Use a Firebase transaction to read the current stock
Inside the transaction, check if stock is enough and update it
Return the updated stock or abort the transaction if not enough stock
💡 Why This Matters
🌍 Real World
This pattern is used in inventory management systems to prevent overselling products by ensuring stock counts are updated safely even with multiple users.
💼 Career
Understanding Firebase transactions is important for developers working on real-time applications that require safe concurrent data updates.
Progress0 / 4 steps
1
Create a Firebase reference to product stock
Create a constant called productStockRef that points to the Firebase Realtime Database path 'products/product123/stock' using firebase.database().ref().
Firebase
Hint
Use firebase.database().ref('path') to get a reference to the database location.
2
Set the order quantity variable
Create a constant called orderQuantity and set it to the number 3.
Firebase
Hint
Use const orderQuantity = 3; to set the order quantity.
3
Write the transaction to read and update stock
Use productStockRef.transaction with a callback function that takes currentStock as input. Inside the function, if currentStock is null, return null. If currentStock is less than orderQuantity, return undefined to abort. Otherwise, return currentStock - orderQuantity.
Firebase
Hint
The transaction callback receives the current value. Return the new value to update or undefined to abort.
4
Add completion handler to transaction
Add a second argument to productStockRef.transaction which is a callback function with parameters error, committed, and snapshot. Inside, if error exists, handle it. If committed is true, the transaction succeeded. Use snapshot.val() to get the updated stock.
Firebase
Hint
The second callback handles the transaction result. Check error and committed flags.
Practice
(1/5)
1. What is the main purpose of using a transaction in Firebase when updating data?
easy
A. To speed up data retrieval from the database
B. To store data permanently without changes
C. To safely read and write data together without conflicts
D. To delete data automatically after a set time
Solution
Step 1: Understand transaction role
Transactions allow reading and writing data atomically, meaning both happen together safely.
Step 2: Identify conflict prevention
This prevents conflicts when multiple users try to update the same data at once.
Final Answer:
To safely read and write data together without conflicts -> Option C
Quick Check:
Transaction = safe read-write [OK]
Hint: Transactions combine read and write safely [OK]
Common Mistakes:
Thinking transactions only speed up reads
Assuming transactions delete data
Believing transactions store data permanently without changes
2. Which of the following is the correct syntax to start a transaction in Firebase Firestore using JavaScript?
easy
A. db.startTransaction(() => { /* code */ })
B. db.transactionStart(() => { /* code */ })
C. db.beginTransaction(async () => { /* code */ })
D. db.runTransaction(async (transaction) => { /* code */ })
Solution
Step 1: Recall Firestore transaction syntax
The correct method to run a transaction is db.runTransaction with an async callback.
Step 2: Check other options
Other options like transactionStart, beginTransaction, or startTransaction are not valid Firestore methods.
A. Missing check if document exists before accessing data
B. Using transaction.update instead of transaction.set
C. Not awaiting transaction.update call
D. Incorrect collection name syntax
Solution
Step 1: Check document existence
The code accesses doc.data().stock without verifying if doc.exists, which can cause errors if doc is missing.
Step 2: Confirm other parts
transaction.update is correct for partial update, awaiting update is not needed as transaction methods handle it, and collection name syntax is correct.
Final Answer:
Missing check if document exists before accessing data -> Option A
Quick Check:
Always check doc.exists before data [OK]
Hint: Always check doc.exists before reading data [OK]
Common Mistakes:
Skipping doc.exists check causing runtime errors
Confusing update with set methods
Expecting to await transaction.update explicitly
5. You want to implement a transaction that increments a user's score only if the current score is less than 100. Which of the following code snippets correctly applies the transaction read-then-write pattern to achieve this?
db.runTransaction(async (transaction) => {
const userRef = db.collection('users').doc('user1');
const doc = await transaction.get(userRef);
if (doc.exists && doc.data().score < 100) {
transaction.update(userRef, { score: doc.data().score + 1 });
}
}); correctly checks if the document exists and if the score is less than 100 before updating.
Step 2: Verify update method and logic
It uses transaction.update to increment the score by 1 only when condition is met, preserving existing data.