Back to blog
Jun 12, 2025
4 min read

Building Offline-First Apps Using IndexedDB and Service Workers

Learn how to build web apps that work seamlessly without an internet connection using IndexedDB for local storage and service workers for caching and offline functionality.

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 idb makes 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