Building Your Learning Module...
Getting things ready for you!
Find videos you like?
Save to resource drawer for future reference!
IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files and blobs. It's a transactional database system that allows you to store and retrieve objects indexed with keys.
Store hundreds of MBs of data (browser-dependent, typically 50MB+)
Non-blocking operations that don't freeze the UI
ACID compliance ensures data integrity
Container for object stores. Each origin (domain) can have multiple databases with different names.
Similar to tables in SQL databases. Stores records (JavaScript objects) with unique keys.
Additional lookup paths to query data by properties other than the primary key.
All read/write operations must happen inside a transaction. Ensures data consistency.
Mechanism to iterate over multiple records in an object store or index.
// Open (or create) a database
const request = indexedDB.open('MyDatabase', 1);
// Handle database upgrade (runs when version changes)
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Create object store (like a table)
if (!db.objectStoreNames.contains('users')) {
const objectStore = db.createObjectStore('users', {
keyPath: 'id', // Primary key
autoIncrement: true // Auto-generate IDs
});
// Create indexes for faster queries
objectStore.createIndex('email', 'email', { unique: true });
objectStore.createIndex('name', 'name', { unique: false });
}
};
// Handle successful opening
request.onsuccess = (event) => {
const db = event.target.result;
console.log('Database opened successfully');
};
// Handle errors
request.onerror = (event) => {
console.error('Database error:', event.target.error);
};onupgradeneeded event only fires when the version number increases or the database is created for the first time. This is where you define your schema.// Assuming 'db' is the opened database
// CREATE - Add a record
function addUser(user) {
const transaction = db.transaction(['users'], 'readwrite');
const objectStore = transaction.objectStore('users');
const request = objectStore.add(user);
request.onsuccess = () => {
console.log('User added:', request.result); // Returns the key
};
request.onerror = () => {
console.error('Error adding user:', request.error);
};
}
// Usage
addUser({ name: 'John Doe', email: 'john@example.com', age: 30 });
// READ - Get a record by key
function getUser(id) {
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const request = objectStore.get(id);
request.onsuccess = () => {
if (request.result) {
console.log('User found:', request.result);
} else {
console.log('User not found');
}
};
}
// READ - Get by index
function getUserByEmail(email) {
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const index = objectStore.index('email');
const request = index.get(email);
request.onsuccess = () => {
console.log('User:', request.result);
};
}
// READ - Get all records
function getAllUsers() {
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const request = objectStore.getAll();
request.onsuccess = () => {
console.log('All users:', request.result);
};
}
// UPDATE - Modify a record
function updateUser(user) {
const transaction = db.transaction(['users'], 'readwrite');
const objectStore = transaction.objectStore('users');
const request = objectStore.put(user); // put() updates or adds
request.onsuccess = () => {
console.log('User updated');
};
}
// DELETE - Remove a record
function deleteUser(id) {
const transaction = db.transaction(['users'], 'readwrite');
const objectStore = transaction.objectStore('users');
const request = objectStore.delete(id);
request.onsuccess = () => {
console.log('User deleted');
};
}class TaskDB {
constructor() {
this.dbName = 'TaskManager';
this.version = 1;
this.db = null;
}
// Initialize database
async init() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains('tasks')) {
const store = db.createObjectStore('tasks', {
keyPath: 'id',
autoIncrement: true
});
store.createIndex('status', 'status', { unique: false });
store.createIndex('priority', 'priority', { unique: false });
}
};
request.onsuccess = (event) => {
this.db = event.target.result;
resolve(this.db);
};
request.onerror = () => reject(request.error);
});
}
// Add task
async addTask(task) {
const transaction = this.db.transaction(['tasks'], 'readwrite');
const store = transaction.objectStore('tasks');
return new Promise((resolve, reject) => {
const request = store.add({
...task,
createdAt: new Date().toISOString()
});
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
// Get all tasks
async getAllTasks() {
const transaction = this.db.transaction(['tasks'], 'readonly');
const store = transaction.objectStore('tasks');
return new Promise((resolve, reject) => {
const request = store.getAll();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
// Get tasks by status
async getTasksByStatus(status) {
const transaction = this.db.transaction(['tasks'], 'readonly');
const store = transaction.objectStore('tasks');
const index = store.index('status');
return new Promise((resolve, reject) => {
const request = index.getAll(status);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
// Update task
async updateTask(task) {
const transaction = this.db.transaction(['tasks'], 'readwrite');
const store = transaction.objectStore('tasks');
return new Promise((resolve, reject) => {
const request = store.put(task);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
// Delete task
async deleteTask(id) {
const transaction = this.db.transaction(['tasks'], 'readwrite');
const store = transaction.objectStore('tasks');
return new Promise((resolve, reject) => {
const request = store.delete(id);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
}
// Usage
const taskDB = new TaskDB();
// Initialize
await taskDB.init();
// Add tasks
const taskId = await taskDB.addTask({
title: 'Learn IndexedDB',
description: 'Study database operations',
status: 'pending',
priority: 'high'
});
// Get all tasks
const tasks = await taskDB.getAllTasks();
console.log('All tasks:', tasks);
// Get pending tasks
const pendingTasks = await taskDB.getTasksByStatus('pending');
// Update task
await taskDB.updateTask({
id: taskId,
title: 'Learn IndexedDB',
status: 'completed',
priority: 'high'
});
// Delete task
await taskDB.deleteTask(taskId);// Iterate over all records with cursor
function iterateAllUsers() {
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const request = objectStore.openCursor();
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
// Process current record
console.log('User:', cursor.value);
// Move to next record
cursor.continue();
} else {
console.log('All users processed');
}
};
}
// Filter with cursor
function findUsersByAge(minAge) {
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const request = objectStore.openCursor();
const results = [];
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
if (cursor.value.age >= minAge) {
results.push(cursor.value);
}
cursor.continue();
} else {
console.log('Filtered users:', results);
}
};
}
// Iterate with index and range
function getUsersInAgeRange(minAge, maxAge) {
const transaction = db.transaction(['users'], 'readonly');
const objectStore = transaction.objectStore('users');
const index = objectStore.index('age');
// IDBKeyRange for filtering
const range = IDBKeyRange.bound(minAge, maxAge);
const request = index.openCursor(range);
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
console.log('User in range:', cursor.value);
cursor.continue();
}
};
}• localStorage: ~5-10MB, synchronous, simple key-value
• IndexedDB: ~50MB+, asynchronous, structured data with indexes
• Cookies: ~4KB, sent to server, simple key-value
Make your code cleaner and easier to work with by wrapping callbacks in promises.
Indexes dramatically improve query performance for large datasets.
Plan your schema changes and test version migrations thoroughly.
Use readonly for reads and readwrite for writes. Transactions auto-commit when all requests complete.
IndexedDB is not encrypted. Never store passwords, credit cards, or sensitive personal information.
Store hundreds of MBs of structured data
Non-blocking operations with promises
Fast lookups with multiple indexes
ACID compliance for data integrity