Bird
Raised Fist0
Node.jsframework~20 mins

Transaction handling in Node.js - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Transaction Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What happens if a transaction is not committed in Node.js with a database client?

Consider a Node.js application using a database client that supports transactions. If you start a transaction but never commit or rollback, what will be the state of the transaction?

Node.js
async function runTransaction(client) {
  await client.query('BEGIN');
  await client.query('INSERT INTO users(name) VALUES($1)', ['Alice']);
  // No COMMIT or ROLLBACK
}
AThe transaction remains open and locks the affected rows until the connection closes or a timeout occurs.
BThe transaction automatically commits after the last query executes.
CThe transaction automatically rolls back after the last query executes.
DThe database throws an error immediately after the INSERT query.
Attempts:
2 left
💡 Hint

Think about what happens when a transaction is left hanging without a commit or rollback.

📝 Syntax
intermediate
2:00remaining
Which option correctly uses async/await to handle a transaction in Node.js?

Given a database client with async query support, which code snippet correctly starts a transaction, inserts a row, commits, and handles errors?

A
async function saveUser(client, name) {
  try {
    await client.query('BEGIN');
    await client.query('INSERT INTO users(name) VALUES($1)', [name]);
  } catch (e) {
    await client.query('ROLLBACK');
  }
  await client.query('COMMIT');
}
B
async function saveUser(client, name) {
  await client.query('BEGIN');
  try {
    await client.query('INSERT INTO users(name) VALUES($1)', [name]);
  } catch (e) {
    await client.query('COMMIT');
  }
}
C
async function saveUser(client, name) {
  await client.query('BEGIN');
  try {
    await client.query('INSERT INTO users(name) VALUES($1)', [name]);
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  }
}
D
async function saveUser(client, name) {
  await client.query('BEGIN');
  await client.query('INSERT INTO users(name) VALUES($1)', [name]);
  await client.query('COMMIT');
  await client.query('ROLLBACK');
}
Attempts:
2 left
💡 Hint

Remember to commit only if no error occurs, and rollback on error.

🔧 Debug
advanced
2:00remaining
Why does this transaction code cause a deadlock?

Examine the following code snippet. Why might it cause a deadlock when multiple instances run concurrently?

Node.js
async function transferFunds(client, fromId, toId, amount) {
  await client.query('BEGIN');
  await client.query('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [amount, fromId]);
  await client.query('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [amount, toId]);
  await client.query('COMMIT');
}
ABecause the updates on accounts are done in different order by concurrent transactions, causing circular waits.
BBecause the transaction does not use explicit locks, so the database deadlocks automatically.
CBecause the COMMIT statement is missing, so the transaction never ends.
DBecause the amount parameter is not validated, causing invalid balance updates.
Attempts:
2 left
💡 Hint

Think about how concurrent transactions lock rows in different orders.

❓ state_output
advanced
2:00remaining
What is the final balance after this transaction code runs successfully?

Assume account 1 has balance 100, account 2 has balance 50. What are their balances after this transaction completes?

Node.js
async function transfer(client) {
  await client.query('BEGIN');
  await client.query('UPDATE accounts SET balance = balance - 30 WHERE id = 1');
  await client.query('UPDATE accounts SET balance = balance + 30 WHERE id = 2');
  await client.query('COMMIT');
}

// Initial balances: account 1 = 100, account 2 = 50
AAccount 1: 100, Account 2: 50
BAccount 1: 70, Account 2: 50
CAccount 1: 130, Account 2: 20
DAccount 1: 70, Account 2: 80
Attempts:
2 left
💡 Hint

Subtract 30 from account 1 and add 30 to account 2.

🧠 Conceptual
expert
2:00remaining
Which statement best describes the ACID property 'Isolation' in database transactions?

Choose the statement that best explains the 'Isolation' property of transactions.

AIsolation guarantees that once a transaction commits, its changes are permanent even if the system crashes.
BIsolation ensures that transactions appear to run sequentially, preventing concurrent transactions from interfering with each other.
CIsolation means that all operations within a transaction are completed successfully or none at all.
DIsolation allows multiple transactions to share the same data without any locking.
Attempts:
2 left
💡 Hint

Think about how transactions behave when running at the same time.

Practice

(1/5)
1. What is the main purpose of using transactions in Node.js database operations?
easy
A. To ensure multiple database actions succeed or fail together
B. To speed up database queries
C. To create multiple database connections
D. To log database errors automatically

Solution

  1. Step 1: Understand the role of transactions

    Transactions group several database actions so they either all succeed or all fail, maintaining data integrity.
  2. Step 2: Compare options

    Only To ensure multiple database actions succeed or fail together correctly describes this purpose. Other options describe unrelated features.
  3. Final Answer:

    To ensure multiple database actions succeed or fail together -> Option A
  4. Quick Check:

    Transaction purpose = group actions for success/failure [OK]
Hint: Transactions keep multiple DB actions atomic and consistent [OK]
Common Mistakes:
  • Thinking transactions speed up queries
  • Confusing transactions with connection pooling
  • Assuming transactions auto-log errors
2. Which of the following is the correct way to start a transaction using a Node.js database client?
easy
A. client.query('START TRANSACTION')
B. client.query('OPEN TRANSACTION')
C. client.query('BEGIN')
D. client.query('INIT TRANSACTION')

Solution

  1. Step 1: Recall standard SQL transaction commands

    The standard command to start a transaction is 'BEGIN'.
  2. Step 2: Validate options

    Only client.query('BEGIN') uses the correct SQL command 'BEGIN'. Other options are invalid SQL commands.
  3. Final Answer:

    client.query('BEGIN') -> Option C
  4. Quick Check:

    Start transaction command = BEGIN [OK]
Hint: Use 'BEGIN' to start transactions in SQL [OK]
Common Mistakes:
  • Using non-standard commands like 'START TRANSACTION'
  • Confusing transaction start with connection open
  • Using commands that don't exist in SQL
3. Consider this Node.js code snippet using a PostgreSQL client:
await client.query('BEGIN');
await client.query('INSERT INTO users(name) VALUES($1)', ['Alice']);
await client.query('COMMIT');
console.log('Transaction complete');
What will be printed if all queries succeed?
medium
A. Transaction complete
B. Error: Transaction failed
C. No output
D. Transaction rolled back

Solution

  1. Step 1: Analyze the transaction flow

    The code starts a transaction, inserts a user, then commits the transaction.
  2. Step 2: Check output after successful commit

    Since all queries succeed, the commit happens and the console logs 'Transaction complete'.
  3. Final Answer:

    Transaction complete -> Option A
  4. Quick Check:

    Successful commit logs message [OK]
Hint: Successful commit prints confirmation message [OK]
Common Mistakes:
  • Assuming errors print without exceptions
  • Confusing commit with rollback output
  • Ignoring async/await behavior
4. Identify the error in this Node.js transaction code snippet:
try {
  await client.query('BEGIN');
  await client.query('INSERT INTO orders(id) VALUES(1)');
  await client.query('COMMIT');
} catch (e) {
  await client.query('ROLLBACK');
  console.error('Transaction failed');
}
medium
A. Missing await before ROLLBACK query
B. No error handling for ROLLBACK failure
C. BEGIN should be after INSERT query
D. COMMIT should be inside catch block

Solution

  1. Step 1: Review transaction error handling

    The code correctly uses try-catch to rollback on error.
  2. Step 2: Identify missing error handling for rollback

    If the ROLLBACK query itself fails, this code does not catch that error, which can cause unhandled exceptions.
  3. Final Answer:

    No error handling for ROLLBACK failure -> Option B
  4. Quick Check:

    Rollback errors need separate handling [OK]
Hint: Always handle errors from ROLLBACK queries too [OK]
Common Mistakes:
  • Assuming ROLLBACK never fails
  • Placing BEGIN after queries
  • Putting COMMIT inside catch block
5. You want to perform two related database inserts in Node.js using transactions. Which pattern correctly ensures both inserts succeed or both fail, releasing the client connection properly?
const client = await pool.connect();
try {
  await client.query('BEGIN');
  await client.query('INSERT INTO accounts(id) VALUES(1)');
  await client.query('INSERT INTO profiles(account_id) VALUES(1)');
  await client.query('COMMIT');
} catch (e) {
  await client.query('ROLLBACK');
  throw e;
} finally {
  client.release();
}
hard
A. Throwing error in catch block breaks transaction
B. client.release() should be called before COMMIT
C. ROLLBACK should be inside finally block
D. This pattern is correct and safely handles transactions and connection release

Solution

  1. Step 1: Check transaction flow and error handling

    The code starts a transaction, performs two inserts, commits if successful, rolls back on error, and rethrows the error.
  2. Step 2: Verify connection release

    The client connection is released in the finally block, ensuring it always happens regardless of success or failure.
  3. Final Answer:

    This pattern is correct and safely handles transactions and connection release -> Option D
  4. Quick Check:

    Try-catch-finally with commit, rollback, release = safe pattern [OK]
Hint: Use try-catch-finally with commit, rollback, and release [OK]
Common Mistakes:
  • Releasing connection too early
  • Placing rollback in finally block
  • Not rethrowing errors after rollback
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard