Atomic order creation with Sequelize transactions
atomicity and transaction handling.
wrap dependent writes in sequelize.transaction, pass the transaction to each query, let managed transactions auto-commit or roll back.
WHAT THIS TESTS Whether you understand atomicity and can correctly thread a transaction through every write so a partial failure leaves no inconsistent state.
A GOOD ANSWER COVERS A transaction groups statements so they all commit or all roll back. Sequelize offers managed transactions: you call sequelize.transaction and pass an async callback. If the callback resolves, Sequelize commits; if it throws, Sequelize automatically rolls back. The critical detail is passing the same transaction object into every query via the transaction option, otherwise that statement runs outside the transaction and commits on its own. For correctness under concurrency you should also lock the product row, for example with a SELECT FOR UPDATE via the lock option, so two simultaneous orders cannot both read the same stock value.
COMMON WRONG ANSWERS Forgetting to pass transaction into one of the queries, using an unmanaged transaction and never calling commit or rollback, or relying on application-level checks instead of a real DB transaction.
LIKELY FOLLOW-UPS Managed versus unmanaged transactions, isolation levels, how locking prevents oversell, and what happens if the commit itself fails.
ONE CONCRETE EXAMPLE await sequelize.transaction(async (t) => { const product = await Product.findByPk(id, { transaction: t, lock: t.LOCK.UPDATE }); if (product.stock < qty) throw new Error('out of stock'); await Order.create(orderData, { transaction: t }); product.stock -= qty; await product.save({ transaction: t }); }); If create or save throws, the lookup, the order, and the decrement all roll back together so stock is never reduced without a matching order.
Read the original → sequelize.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.