Object Stores and Keys
What Is an Object Store?
Section titled “What Is an Object Store?”An object store is IndexedDB’s equivalent of a database table. Each record in an object store is a JavaScript object — but unlike a SQL table, there is no schema enforcement. You can store objects with different shapes in the same store. The only structural rule is how the key is determined.
Think of it this way:
- A SQL table row has a fixed set of columns.
- An object store record is any JS object you hand it, plus a key that uniquely identifies it.
Creating an Object Store
Section titled “Creating an Object Store”You create object stores by calling db.createObjectStore(name, options) on the database instance. This method must be called inside the onupgradeneeded event handler — it is only valid during a version upgrade.
const request = indexedDB.open('my-db', 1);
request.onupgradeneeded = (event) => { const db = event.target.result; db.createObjectStore('contacts', { keyPath: 'id' });};The first argument is the store name. The second argument is an options object controlling how keys work.
keyPath: In-Line Keys
Section titled “keyPath: In-Line Keys”When you set keyPath, the store uses a property on the stored object as its key. This is called an in-line key because the key lives inside the object itself.
// Every object you store MUST have an `id` propertydb.createObjectStore('contacts', { keyPath: 'id' });
// Valid record:
// Invalid — no `id` field, will throw:store.add({ name: 'Bob' });If you set autoIncrement: true alongside keyPath, the browser generates the key automatically and writes it into the object at the specified path:
db.createObjectStore('contacts', { keyPath: 'id', autoIncrement: true });
// `id` will be filled in automatically:store.add({ name: 'Alice' }); // stored as { id: 1, name: 'Alice' }Out-of-Line Keys
Section titled “Out-of-Line Keys”When you omit keyPath (or set it to null), the key is separate from the object. This is called an out-of-line key. You supply it manually as the second argument to add() or put().
db.createObjectStore('raw-blobs', { keyPath: null });
// You provide the key explicitly:store.add({ data: '...' }, 'blob-001');Combine with autoIncrement: true to let the browser generate integer keys without touching the stored object:
db.createObjectStore('logs', { autoIncrement: true });
// No key needed — browser assigns 1, 2, 3, ...store.add({ level: 'info', message: 'App started' });Key Mode Comparison
Section titled “Key Mode Comparison”| Mode | keyPath | autoIncrement | Key source |
|---|---|---|---|
| In-line (explicit) | 'id' | false | Object’s id field |
| In-line (auto) | 'id' | true | Auto-generated, stored in id |
| Out-of-line (manual) | (none) | false | Caller provides key |
| Out-of-line (auto) | (none) | true | Auto-generated, not in object |
Try It: Creating Two Object Stores
Section titled “Try It: Creating Two Object Stores”The example below opens a database at version 1 and creates two stores:
contacts— in-line key using theidpropertylogs— out-of-line auto-incrementing key
Run it to see both store names printed to the console.