Building Offline-First Apps Using IndexedDB and Service Workers
In today’s always-connected world, it’s easy to assume that web apps will have uninterrupted internet access. But users frequently lose connectivity , on the subway, during travel, or in remote areas. That’s where offline-first applications come in. They’re designed to work reliably even when a user goes offline, enhancing both performance and user experience.
With IndexedDB and Service Workers, you can build resilient web apps that cache assets, store user data locally, and synchronize with the server once connectivity is restored. This approach not only improves accessibility but also reduces server load and improves app responsiveness.
What Does “Offline-First” Mean?
An offline-first app is one that assumes the user may not have a network connection. Instead of failing when the internet is down, it:
- Loads cached content
- Stores new or changed data locally
- Syncs with the backend when online
This is especially useful for:
- Note-taking or productivity apps
- E-commerce carts
- Messaging or journaling tools
- Any app requiring reliability in fluctuating network conditions
Core Technologies: IndexedDB and Service Workers
IndexedDB
- A low-level browser database that stores structured data on the client side
- Allows large amounts of data (better than
localStorage) - Asynchronous and promise-based (using wrappers like
idbmakes it easier)
Service Workers
- Scripts that run in the background
- Can intercept and cache network requests
- Enable features like push notifications and offline access
- Work independently of your app’s main thread
Together, they form the backbone of offline capabilities in modern PWAs (Progressive Web Apps).
Getting Started: Setting Up IndexedDB
Install the idb wrapper for IndexedDB:
npm install idb
Create a simple IndexedDB utility:
import { openDB } from 'idb';
const dbPromise = openDB('my-app-db', 1, {
upgrade(db) {
db.createObjectStore('notes', { keyPath: 'id' });
},
});
export const saveNote = async (note) => {
const db = await dbPromise;
await db.put('notes', note);
};
export const getAllNotes = async () => {
const db = await dbPromise;
return db.getAll('notes');
};
Now, when a user adds or updates data, it can be stored locally without needing to be sent immediately to the server.
Setting Up a Service Worker
In your main JS file or React app, register the service worker:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').then(reg => {
console.log('Service worker registered.', reg);
});
});
}
Create public/sw.js:
const CACHE_NAME = 'app-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/styles.css',
'/main.js',
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache))
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => response || fetch(event.request))
);
});
This simple service worker caches essential files and serves them when offline.
Syncing with the Server
When the user comes back online, you can detect network availability and sync:
window.addEventListener('online', async () => {
const notes = await getAllNotes();
for (let note of notes) {
await fetch('/api/sync-note', {
method: 'POST',
body: JSON.stringify(note),
});
// Optionally, remove synced note from IndexedDB
}
});
For more advanced handling, consider using the Background Sync API, though it’s not supported in all browsers.
Best Practices
- Keep your offline cache size reasonable
- Use IndexedDB for dynamic, structured data
- Serve skeleton UI while offline and update when online
- Test offline functionality thoroughly using browser dev tools
- Clearly communicate sync status to users (e.g., “Changes will be saved when back online”)
Conclusion
Offline-first design is more than a fallback , it’s a strategy that respects your users’ time, bandwidth, and reliability needs. By using IndexedDB for local storage and Service Workers for caching and request handling, you can create web apps that feel native, responsive, and resilient.
In an unpredictable digital world, offline-first is quickly becoming not just a feature , but a necessity.
Disclaimer
Article written with the help of AI.
Read the full Disclaimer HERE