What if your app could catch conflicts before they erase your work?
Why Optimistic concurrency in Firebase? - Purpose & Use Cases
Imagine two friends trying to edit the same Google Doc at the same time without any warning. They both make changes, but only one friend's edits get saved, and the other loses their work without knowing.
Manually handling simultaneous updates is slow and confusing. Without a system to check if data changed before saving, you risk overwriting someone else's work or causing errors that are hard to fix.
Optimistic concurrency lets you try saving your changes but first checks if the data was changed by someone else. If it was, you get notified and can decide how to merge or retry, avoiding silent overwrites.
saveData(newData) // blindly overwrites existing data
saveData(newData, lastKnownVersion) // checks version before saving
It enables safe, smooth collaboration where multiple users can update data without accidentally erasing each other's work.
In a shared shopping list app, optimistic concurrency prevents one person's item removal from erasing another's recent additions made at the same time.
Manual updates risk overwriting others' changes silently.
Optimistic concurrency checks data versions before saving.
This keeps data safe and collaboration smooth.
Practice
Solution
Step 1: Understand optimistic concurrency concept
Optimistic concurrency means checking if data changed before saving updates to avoid overwriting others' changes.Step 2: Match concept to Firebase usage
Firebase uses transactions to check and update data atomically, which is an example of optimistic concurrency.Final Answer:
To prevent overwriting data by checking for changes before updating -> Option DQuick Check:
Optimistic concurrency = prevent overwrites [OK]
- Confusing optimistic concurrency with caching
- Thinking it encrypts data
- Assuming it backs up data automatically
Solution
Step 1: Identify methods for data update in Firebase
Methods like set() overwrite data directly, push() adds new data, once() reads data once.Step 2: Find method supporting atomic update with retry
transaction() reads current data, applies update, retries if data changed during update, ensuring safe concurrency.Final Answer:
firebase.database().transaction() -> Option BQuick Check:
Safe update method = transaction() [OK]
- Using set() which overwrites without concurrency check
- Confusing push() with update methods
- Using once() which only reads data
const ref = firebase.database().ref('counter');
ref.transaction(current => {
return (current || 0) + 1;
});What happens if two users run this code at the same time?
Solution
Step 1: Understand transaction behavior with concurrent updates
Firebase transactions read current value, apply update, and retry if data changed during update.Step 2: Analyze two concurrent increments
Both users read current value, increment by 1, but Firebase retries one transaction to avoid overwrite, resulting in counter increasing by 2.Final Answer:
The counter increments by 2 safely without overwriting -> Option CQuick Check:
Concurrent transactions = safe increments [OK]
- Thinking only one increment happens
- Assuming counter resets
- Believing transaction throws error on conflict
ref.transaction(current => {
current = current + 1;
return current;
});But sometimes it throws an error. What is the likely problem?
Solution
Step 1: Check how current value is used
If current is null (no data yet), adding 1 to null causes an error.Step 2: Identify fix for null current
Use (current || 0) + 1 to handle null safely inside transaction.Final Answer:
current might be null, causing addition to fail -> Option AQuick Check:
Null current causes error in addition [OK]
- Thinking transaction can't update numbers
- Trying to use set() inside transaction callback
- Believing arrow functions are unsupported
Solution
Step 1: Understand concurrency risks with simple set()
Using set() without checking current value risks overwriting likes if multiple users update simultaneously.Step 2: Use transaction for atomic increments
transaction() reads current value, increments safely, and retries if data changed, ensuring correct count.Step 3: Evaluate other options
Reading once then setting risks race conditions; push() adds entries but does not increment counter directly.Final Answer:
Use ref.transaction(currentLikes => (currentLikes || 0) + 1) to increment safely -> Option AQuick Check:
Safe counter update = transaction() increment [OK]
- Using set() without concurrency control
- Reading once then setting causing race conditions
- Confusing push() with incrementing counters
Ready to prove it?
Pass the test and this pattern moves unknown
