IndexedDB: A client database for lightning and offline applications

Imagine: a user logs into your web application - an online store, a fintech service, or a gaming platform — on the subway, where the connection is unstable. The page takes forever to load, the shopping cart is not updated, and key functionality is unavailable. The result? Irritation and a closed tab. In Russia, with its vast territory and different communication quality, this is not a rare case, but a daily reality for millions.
How can you save the user and give them a seamless experience, even when the network has failed?
The answer is the transition from server-first to client-first architecture.
And the heart of this client-side approach is IndexedDB.
What is IndexedDB?
IndexedDB (Indexed Database API) is a full-fledged, NoSQL-like database built directly into the user’s browser. It’s not just “another storage” like localStorage or Cookies.
IndexedDB is like a built—in warehouse inside your browser. If localStorage is a small safe for several securities (key-value), then IndexedDB is a huge logistics center where you can store entire catalogs of goods, order history, draft documents, and complex data structures, and then instantly find what you need for any parameter.
Key features that are important to understand
-
Asynchronous: All operations take place in the background without blocking the main stream and interface
-
Stores large amounts: Theoretically, the limits are huge (usually 50-80% of the free disk space), which allows you to store gigabytes of data
-
Supports transactions: As in “adult” databases, which guarantees data integrity
-
Works with complex structures: You can store objects, files, blobs — almost anything
How does IndexedDB work?
The principle of operation of IndexedDB differs from simple key-value repositories. Here are his basic concepts
-
Database: One database is being created for your application (or domain). Each database has a version, which is critical for managing the data structure.
-
Object Stores: These are analogs of tables in relational databases. For example, for an online store, you can create repositories for products, users, cart.
-
Indexes: That’s where the real power lies! You can create indexes for any fields of your objects. Do you want to quickly find products by category or price? Create an index, and the search will be lightning fast, without going through all the records.
-
Requests and Cursors: To receive data, you make requests. If you need to go through a set of data (for example, all the items in the basket), you use cursors.
-
Transactions: Any interaction with data (read, write) occurs within a transaction. This ensures that either all operations inside it are performed, or none, which protects your data from corruption.
A simple analogy: Imagine that you are a librarian. The database is the entire library. Object storages are shelving (fiction, scientific, periodicals). Indexes are catalog cards sorted by title, author, or year of publication. A transaction is the process of giving a book to a reader: you find a book in a catalog (index), go to a shelf (storage), pick it up and mark it in a journal — all these actions either occur entirely or do not occur at all.
IndexedDB in the context of the Client-First approach
Client-First is an architectural pattern where the main logic and data are first processed on the client side, and the server acts as a synchronized backend.
1. Offline Work and Resilience
Your app works without any network at all. The user can view the cached product catalog, fill the shopping cart, and edit the profile. All data is written to IndexedDB. As soon as the connection is restored, a special background process synchronizes the changes with the server.
- The Russian case: The user of “Sbermarket” or “Yandex.Food” adds groceries to the basket in an elevator where there is no network. Once outside, the shopping cart is ready to be ordered.
2. Lightning-fast performance
The data is already on the user’s device. You don’t need to wait for a network request to draw the interface. This drastically reduces the Time to Interactive (TTI).
- Russian case study: The social network VKontakte uses similar technologies to instantly download news feeds and personal messages.
3. Reducing server load
Fewer API requests to get the same data (for example, city directories or a list of categories). Static data is loaded once and then taken from the local database.
4. Effective management of big data
If your application works with large datasets (for example, graphs, analytics, catalogs with thousands of items), loading them all into RAM (as in Redux) is inefficient. IndexedDB allows you to work with data in chunks, through cursors.
How to use IndexedDB? A practical example for your project
Theory without practice is dead. Let’s look at a basic example of working with IndexedDB in JavaScript.
Task: Create a database for caching online store products.
// Opening or creating a database
const request = indexedDB.open('MyShopDB', 1); // 'MyShopDB' - name, 1st version
let db;
// It is triggered if the database needs to be created or updated.
request.onupgradeneeded = function(event) {
db = event.target.result;
// Creating a repository of 'products' objects with the 'id' key
const productStore = db.createObjectStore('products', { keyPath: 'id' });
// Creating an index for searching by category 'category'
productStore.createIndex('by_category', 'category', { unique: false });
};
// It is triggered when the database is opened successfully.
request.onsuccess = function(event) {
db = event.target.result;
console.log('База данных открыта');
};
// It is triggered by an error
request.onerror = function(event) {
console.error('Ошибка базы данных:', event.target.errorCode);
};
// A function for adding a product
function addProduct(product) {
// Creating a write transaction for the 'products' storage
const transaction = db.transaction(['products'], 'readwrite');
const store = transaction.objectStore('products');
const request = store.add(product);
request.onsuccess = function() {
console.log('Товар добавлен в IndexedDB');
};
request.onerror = function() {
console.log('Ошибка при добавлении товара');
};
}
// A function for getting all products by category
function getProductsByCategory(category) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['products'], 'readonly');
const store = transaction.objectStore('products');
const index = store.index('by_category'); // Using the index
// We receive all products with the specified category
const request = index.getAll(category);
request.onsuccess = function() {
resolve(request.result);
};
request.onerror = function() {
reject(request.error);
};
});
}
// Usage example
const newProduct = { id: 123, name: 'Смартфон', category: 'electronics', price: 29999 };
addProduct(newProduct);
// Later, to get all the electronics
getProductsByCategory('electronics').then(products => {
console.log(products); // Displays an array of products, including our smartphone
});
What it can be used for right now:
-
Caching of the catalog for offline viewing.
-
Draft order or shopping cart.
-
Caching of data for dashboards and analytical reports.
-
Storing user settings and UI status.
Best practices and pitfalls
-
Error handling: Always handle onerror. The browser can clear your database if it needs space.
-
Version control: Changing the database structure (creating new repositories/indexes) is possible only when updating the version. Plan it in advance.
-
Use libraries: The native API is cumbersome. For production, use proven libraries such as Dexie.js or idb. They make the code much cleaner and simpler.
-
Support Check: Always check window.IndexedDB before using.
Conclusion
IndexedDB is not a niche technology, but a powerful tool for creating a modern, competitive web application, especially in the context of the Russian market with its connectivity specifics. Switching to a client-first approach using IndexedDB allows you to:
-
Increase user satisfaction.
-
Increase retention and conversions.
-
Create a fault-resistant product.
Start small by implementing catalog caching or shopping cart. You will immediately see how your product will become faster, more reliable and more independent.

