What if one tiny mistake in your data update could break your whole app's trustworthiness?
Why Transactions in NestJS? - Purpose & Use Cases
Imagine you are manually updating multiple database tables for an online order: deducting stock, creating the order record, and updating the user's purchase history.
If one step fails, you have to manually undo all previous changes to avoid data mistakes.
Manually tracking each step is slow and error-prone.
If you forget to undo one change, your data becomes inconsistent and unreliable.
This can cause bugs, lost money, or unhappy users.
Transactions let you group all these steps into one safe block.
If anything goes wrong, the whole group is rolled back automatically, keeping your data clean and consistent.
try { updateStock(); createOrder(); updateUserHistory(); } catch { rollbackChanges(); }await connection.transaction(async manager => { await manager.updateStock(); await manager.createOrder(); await manager.updateUserHistory(); });Transactions make complex data updates safe and reliable with minimal effort.
When a customer places an order, transactions ensure stock is reduced only if the order is saved and payment is processed, preventing errors like selling items that aren't available.
Manual data updates can cause inconsistent states if errors happen.
Transactions group multiple steps into one safe operation.
They automatically undo all changes if something fails, keeping data reliable.
Practice
Solution
Step 1: Understand what transactions do
Transactions group multiple database actions so they either all succeed or all fail, preventing partial updates.Step 2: Identify the purpose in NestJS context
In NestJS, transactions keep data consistent by ensuring grouped operations are atomic.Final Answer:
To ensure multiple database operations succeed or fail together -> Option BQuick Check:
Transactions = atomic operations [OK]
- Thinking transactions speed up queries
- Confusing transactions with schema generation
- Assuming transactions are for logging only
Solution
Step 1: Recall TypeORM transaction method
TypeORM uses dataSource.transaction with an async callback to run transactional code.Step 2: Check method names
Only dataSource.transaction(async (manager) => { /* operations */ }) uses the correct method name and async callback pattern.Final Answer:
dataSource.transaction(async (manager) => { /* operations */ }) -> Option AQuick Check:
Correct method is transaction with async callback [OK]
- Using non-existent methods like startTransaction
- Omitting async keyword in callback
- Using wrong method names like begin or runTransaction
await dataSource.transaction(async (manager) => {
await manager.save(user1);
await manager.save(user2); // throws error
});
console.log('Transaction complete');Solution
Step 1: Understand transaction rollback behavior
If any operation inside the transaction fails, all changes are rolled back, so no data is saved.Step 2: Analyze the code flow
The second save throws an error, so the transaction aborts and neither user1 nor user2 are saved. The error prevents reaching the console.log.Final Answer:
Neither user1 nor user2 are saved, and an error is thrown before logging -> Option AQuick Check:
Transaction rollback on error = no saves, error thrown [OK]
- Assuming partial saves happen before error
- Thinking console.log runs despite error
- Believing transaction commits despite failure
await dataSource.transaction(async (manager) => {
manager.save(user1);
await manager.save(user2);
});Solution
Step 1: Check async calls inside transaction
All asynchronous operations inside the transaction callback must be awaited to ensure proper execution order.Step 2: Identify missing await
The first save call lacks await, so it may not complete before the second save starts, causing unexpected behavior.Final Answer:
Missing await before manager.save(user1) -> Option CQuick Check:
Await all async DB calls inside transaction [OK]
- Omitting await on async calls
- Thinking transaction callback can't be async
- Believing manager.save is disallowed in transactions
async updateEntities(entityA, entityB) {
await this.dataSource.transaction(async (manager) => {
await manager.save(entityA);
await manager.save(entityB);
});
}
What is the best practice to handle errors and maintain data consistency?Solution
Step 1: Understand transaction error handling in TypeORM
TypeORM automatically rolls back if an error is thrown inside the transaction callback.Step 2: Use try-catch outside transaction to handle errors
Wrapping the transaction call in try-catch lets you catch errors and respond without manual rollback calls.Final Answer:
Wrap the transaction call in try-catch and handle rollback automatically -> Option DQuick Check:
Try-catch outside transaction handles errors; rollback is automatic [OK]
- Trying to manually rollback inside transaction callback
- Using separate transactions for related updates
- Ignoring transactions and relying only on DB constraints
Ready to prove it?
Pass the test and this pattern moves unknown
