Transactions ensure that a group of DB operations either ALL succeed or ALL fail.

Think of it like:

"Either everything commits OR nothing changes."

This is critical for cases like:


🔹 Basic Transaction Pattern

import { sequelize } from "../Db/db.index.js";

const t = await sequelize.transaction();

try {
  // Example DB operations
  const user = await User.create({ name: "Abhi" }, { transaction: t });

  const profile = await Profile.create(
    { userId: user.id, bio: "Hello" },
    { transaction: t }
  );

  await t.commit(); // ✅ everything succeeded
  console.log("Transaction committed");
} catch (error) {
  await t.rollback(); // ❌ revert everything
  console.log("Transaction rolled back");
}


🔹 Recommended Pattern (Cleaner + Uses Callback)

await sequelize.transaction(async (t) => {
  const user = await User.create(
    { name: "Abhi" },
    { transaction: t }
  );

  await Profile.create(
    { userId: user.id, bio: "Software Engineer" },
    { transaction: t }
  );

  // No need to manually commit or rollback
});

If an error occurs inside the function → Sequelize auto-rolls back.


💣 Real Example: Wallet Money Transfer

await sequelize.transaction(async (t) => {
  const sender = await User.findByPk(senderId, { transaction: t });
  const receiver = await User.findByPk(receiverId, { transaction: t });

  if (sender.balance < amount) {
    throw new Error("Insufficient balance");
  }

  await sender.update(
    { balance: sender.balance - amount },
    { transaction: t }
  );

  await receiver.update(
    { balance: receiver.balance + amount },
    { transaction: t }
  );
});

If anything fails (network, DB constraint, insufficient balance) → money is NOT partially transferred.


👍 When to Use Transactions