IndexedDB Transactions: The Gatekeepers of Data

An IndexedDB transaction is a short-lived container for all database operations, ensuring data integrity. Use it for any read or write. The main footgun: transactions auto-commit if idle, so you must queue all requests synchronously without waiting.
Why it exists
IndexedDB is designed for reliable client-side storage. To prevent data corruption from concurrent operations, all reads and writes must happen inside a transaction. This ensures that a series of operations either all succeed as a single unit or all fail, leaving the database in a consistent state.
The mental model
Think of an IndexedDB transaction as a temporary, protected session with your database. You tell it which "rooms" (object stores) you need to access and whether you'll be just looking (readonly) or changing things (readwrite). The session stays open only as long as you are actively making database requests within it.
How it works
You start a transaction by calling db.transaction() on your database connection, specifying the object stores and mode. The transaction is active immediately. You then get a reference to an object store from the transaction and queue up all your requests (like get(), put(), delete()) synchronously. The browser executes these requests. The transaction remains active only during the initial creation and in the event handlers for its requests. If the event loop ticks and the transaction has no pending requests and no new ones were added, it automatically commits. If any request fails and the error is not handled, the entire transaction aborts and all its changes are rolled back.
When to use it
You must use a transaction for any data access in IndexedDB; it is not optional. The key decision is the mode. Use readonly for fetching data; it's faster and allows multiple readonly transactions to run concurrently. Use readwrite for creating, updating, or deleting data; this mode is exclusive and locks the specified object stores to prevent conflicts.
When not to use it
The footgun is trying to hold a transaction open across asynchronous operations that are not IndexedDB requests. For example, do not make a fetch() call and then try to use its result in the same transaction. The transaction is "inactive" while waiting for the network and will auto-commit before your fetch completes. All database requests for a single transaction must be queued in the same initial block of code.
One canonical example
To update a user's profile and then read another, you must queue both requests without interruption.
const tx = db.transaction("users", "readwrite");
const store = tx.objectStore("users");
store.put({ id: 123, name: "Alice", email: "new@email.com" });
store.get(456);
tx.oncomplete = () => { console.log("All requests in the transaction are complete!"); };
tx.onerror = (event) => { console.error("Transaction failed:", event.target.error); };Interview question
What is a critical constraint to remember when structuring operations within an IndexedDB transaction?
- a.All database operations within a transaction must be explicitly committed by the developer.
- b.Readonly transactions are always preferred over readwrite transactions for better performance.
- c.Database requests must be queued synchronously without waiting for non-IndexedDB asynchronous operations.Correct
- d.A transaction can only access a single object store at a time to maintain data consistency.
Why? this is the answer
The card highlights that the 'footgun' is attempting to queue database requests after a non-IndexedDB asynchronous operation within the same transaction, as the transaction will auto-commit while waiting. Therefore, all database requests must be queued synchronously. Transactions auto-commit when idle, so explicit commitment is not required, making option A incorrect.
Just read this? Test yourself on what you have been reading.
Read the original → developer.mozilla.org
- #indexeddb
- #web apis
- #transactions
- #browser storage
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles