Both or neither
BEGIN;
INSERT INTO lessons VALUES (5, 1, 3, '2026-03-10', 60);
UPDATE guests SET balance = balance - 60 WHERE id = 1;
SELECT changes() AS guests_debited;
COMMIT;
Desktop only. One booking, one debit, one decision.A coaching booking at Harbor Snow is two writes: insert the booking, debit the guest's prepaid balance. If the second one fails, the first one is a booking nobody paid for. A transaction makes the two succeed or fail together: BEGIN, both writes, check changes() and the balance, then COMMIT when it is right or ROLLBACK when it is not.
The part people get wrong: a failing statement inside a transaction does not undo the ones before it. When the debit is refused by the balance's CHECK, the transaction is still open and the booking insert is still pending. Nothing is committed and nothing is undone until you say which. The error is information; ROLLBACK is the decision.
The browser playground runs one statement at a time on a copy, so it cannot hold a transaction open. Transactions are a desktop skill: open the Harbor Snow kit in the sqlite3 shell, enter each statement separately, and watch the balances between them.
Rule of thumb. Inside a transaction an error pauses; it does not undo. You decide with COMMIT or ROLLBACK.
Going deeper (optional, not on the exam)
The sqlite3 shell's .bail on stops a script at the first error. That is not a rollback: everything before the error that was not inside a transaction has already happened. Use a fresh rehearsal copy to retry.