📖 Scenario: You are building a simple NestJS service to manage bank accounts. You want to ensure that money transfers between accounts happen safely using transactions, so that either both accounts update correctly or none do.
🎯 Goal: Build a NestJS service method that uses transactions to transfer money between two accounts safely.
📋 What You'll Learn
Create an initial accounts data structure with two accounts and their balances
Add a variable to hold the transfer amount
Write a service method that uses a transaction to update both accounts
Complete the transaction handling with commit and rollback logic
💡 Why This Matters
🌍 Real World
Transactions ensure that money transfers between accounts happen safely without data loss or corruption.
💼 Career
Understanding transactions is essential for backend developers working with databases and NestJS to build reliable financial or data-critical applications.
Progress0 / 4 steps
1
Create initial accounts data
Create a variable called accounts as a JavaScript object with two keys: accountA with value 1000 and accountB with value 500.
NestJS
Hint
Use a JavaScript object with keys accountA and accountB and assign the given balances.
2
Add transfer amount variable
Add a constant variable called transferAmount and set it to 200.
NestJS
Hint
Use const transferAmount = 200; to define the amount to transfer.
3
Write transfer method with transaction
Write an async function called transferMoney that accepts no parameters. Inside, use a try block to simulate starting a transaction by logging 'Transaction started'. Then subtract transferAmount from accounts.accountA and add it to accounts.accountB. After that, log 'Transaction committed'. Add a catch block that logs 'Transaction rolled back' if an error occurs.
NestJS
Hint
Use try and catch blocks inside an async function to simulate transaction behavior.
4
Complete transaction with NestJS style
Modify the transferMoney function to accept a queryRunner parameter. Use await queryRunner.startTransaction() at the start, then update the accounts. After updating, use await queryRunner.commitTransaction(). In the catch block, use await queryRunner.rollbackTransaction(). Finally, use await queryRunner.release() in a finally block.
NestJS
Hint
Use await with queryRunner methods to handle the transaction lifecycle properly.
Practice
(1/5)
1. What is the main purpose of using transactions in a NestJS application with a database?
easy
A. To automatically generate database schemas
B. To ensure multiple database operations succeed or fail together
C. To speed up database queries by caching results
D. To log all database queries for debugging
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 B
Quick Check:
Transactions = atomic operations [OK]
Hint: Transactions keep grouped DB actions all-or-nothing [OK]
Common Mistakes:
Thinking transactions speed up queries
Confusing transactions with schema generation
Assuming transactions are for logging only
2. Which of the following is the correct way to start a transaction using TypeORM's DataSource in NestJS?
easy
A. dataSource.transaction(async (manager) => { /* operations */ })
B. dataSource.startTransaction(() => { /* operations */ })
C. dataSource.begin(async () => { /* operations */ })
D. dataSource.runTransaction(() => { /* operations */ })
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.
A. dataSource.transaction requires a synchronous callback
B. Transaction callback should not be async
C. Missing await before manager.save(user1)
D. manager.save cannot be used inside transactions
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 C
Quick Check:
Await all async DB calls inside transaction [OK]
Hint: Always await async DB calls inside transaction [OK]
Common Mistakes:
Omitting await on async calls
Thinking transaction callback can't be async
Believing manager.save is disallowed in transactions
5. You want to update two related entities atomically in NestJS using TypeORM transactions. Which approach correctly ensures both updates succeed or fail together?