CRUD Operations
The CRUD method reference
Section titled “The CRUD method reference”Every data operation in IndexedDB goes through an IDBObjectStore. You obtain a store from a transaction, then call one of these six methods:
| Method | Mode needed | Description |
|---|---|---|
add(value) | readwrite | Adds a new record; throws ConstraintError if the key already exists |
put(value) | readwrite | Adds or overwrites (upsert); never throws on duplicate key |
get(key) | readonly | Returns one record, or undefined if the key is absent |
getAll() | readonly | Returns an array of all records in the store |
delete(key) | readwrite | Removes the record with the given key; no-op if absent |
count() | readonly | Returns the total number of records |
Every method returns an IDBRequest. The result is available inside the request’s onsuccess callback as request.result.
add vs put
Section titled “add vs put”add(value) is strictly for new records. If a record with the same key path value already exists, the request fires onerror with a ConstraintError — the record is not written.
put(value) is an upsert: it writes the record whether or not the key already exists. Use put when you want “create or update” semantics without checking first.
const tx = db.transaction(['products'], 'readwrite');const store = tx.objectStore('products');
// add — safe only when id 1 does not exist yetstore.add({ id: 1, name: 'Apple', price: 1.5 });
// put — always safe; overwrites if id 1 is already therestore.put({ id: 1, name: 'Apple', price: 1.99 });get returns undefined, not null
Section titled “get returns undefined, not null”This is different from Web Storage, where a missing key returns null. With IndexedDB, get(key) resolves to undefined when no record matches. Always check === undefined, not !result, to distinguish a missing record from a record that stores a falsy value.
const tx = db.transaction(['products'], 'readonly');const store = tx.objectStore('products');const req = store.get(999);
req.onsuccess = () => { console.log(req.result); // undefined — key 999 does not exist};Wrapping IDBRequest in a Promise
Section titled “Wrapping IDBRequest in a Promise”Raw IDBRequest callbacks are verbose. A tiny helper makes every store method await-able:
function promisifyReq(r) { return new Promise((res, rej) => { r.onsuccess = () => res(r.result); r.onerror = () => rej(r.error); });}
// Now you can await any store methodconst apple = await promisifyReq(store.get(1));