🎯 What You'll Learn

    • localStorage vs sessionStorage vs IndexedDB
    • Building a Storage Service Layer
    • TTL-based caching
    • Storing files & blobs in IndexedDB
    • Cross-tab communication
    • Offline-first sync architecture

    💡 Running Code Locally: While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:

    • Download Node.js to run JavaScript on your computer
    • Use your browser's Developer Console (Press F12) to test code snippets
    • Create a .html file with <script> tags and open it in your browser

    Web Storage APIs

    Master localStorage, sessionStorage, and IndexedDB to build fast, offline-friendly applications with persistent client-side data.

    Understanding the Storage Landscape

    JavaScript provides three powerful storage mechanisms, each designed for different needs:

    localStorage

    • • Persists forever
    • • Shared across tabs
    • • ~5-10 MB limit
    • • Synchronous

    sessionStorage

    • • Deleted when tab closes
    • • Isolated per tab
    • • ~5-10 MB limit
    • • Synchronous

    IndexedDB

    • • Persists forever
    • • Stores objects & blobs
    • • Hundreds of MB+
    • • Asynchronous

    localStorage: Long-Term Persistent Storage

    localStorage keeps data forever (or until the user clears it manually). It's ideal for preferences, themes, cached data, and recently viewed items.

    localStorage Basics

    Learn how to store and retrieve data with localStorage

    Try it Yourself »
    JavaScript
    // localStorage keeps data forever (until manually cleared)
    // Perfect for: preferences, theme, cached data, recently viewed
    
    localStorage.setItem("theme", "dark");
    const theme = localStorage.getItem("theme");
    console.log("Theme:", theme); // "dark"
    
    localStorage.removeItem("theme");
    localStorage.clear(); // removes all items
    
    // Values are ALWAYS strings - must convert objects
    localStorage.setItem("user", JSON.stringify({ id: 10, role: "admin" }));
    const user = JSON.parse(localStorage.getItem("
    ...

    Common Mistakes to Avoid

    localStorage Common Mistakes

    Avoid these common localStorage pitfalls

    Try it Yourself »
    JavaScript
    // ❌ COMMON MISTAKE - string concatenation
    localStorage.setItem("count", 1);
    console.log(localStorage.getItem("count") + 1); // "11" (string!)
    
    // ✔ CORRECT - convert to number first
    localStorage.setItem("count", 1);
    console.log(Number(localStorage.getItem("count")) + 1); // 2
    
    // ❌ Another mistake - forgetting to stringify
    localStorage.setItem("data", { name: "test" }); // stores "[object Object]"
    
    // ✔ CORRECT
    localStorage.setItem("data", JSON.stringify({ name: "test" }));

    sessionStorage: Tab-Specific, Temporary Storage

    sessionStorage is deleted when the tab closes. It's perfect for multi-step forms, temporary shopping cart state, and tab-isolated workflows.

    sessionStorage Example

    Learn tab-specific temporary storage

    Try it Yourself »
    JavaScript
    // sessionStorage is deleted when the tab closes
    // Perfect for: multi-step forms, temp state, tab-specific data
    
    sessionStorage.setItem("step", "payment");
    console.log(sessionStorage.getItem("step")); // "payment"
    
    // Each tab has SEPARATE storage!
    // Open two tabs → each has its own sessionStorage
    
    // Great for checkout flows
    sessionStorage.setItem("cartDraft", JSON.stringify({
      items: [{ id: 1, qty: 2 }],
      step: 2
    }));
    
    // Prevents data bleed between tabs
    sessionStorage.setItem("tabId", cry
    ...

    localStorage vs sessionStorage

    FeaturelocalStoragesessionStorage
    PersistenceUntil clearedUntil tab closes
    ScopeShared across tabsPer-tab isolation
    Use casePreferences & saved stateIn-progress workflows

    Building a Storage Service Layer

    Production apps don't store values directly into localStorage. They create a Storage Service Layer that centralizes logic, handles parsing errors, and adds features like namespacing.

    Storage Service Layer

    Build a production-ready storage wrapper

    Try it Yourself »
    JavaScript
    // Production apps use a Storage Service Layer
    class StorageService {
      constructor(prefix = "app") {
        this.prefix = prefix;
      }
    
      key(name) {
        return `${this.prefix}:${name}`;
      }
    
      get(name, fallback = null) {
        try {
          const value = localStorage.getItem(this.key(name));
          return value ? JSON.parse(value) : fallback;
        } catch {
          return fallback;
        }
      }
    
      set(name, value) {
        localStorage.setItem(this.key(name), JSON.stringify(value));
      }
    
      remove(name) {
        l
    ...

    TTL-Based Storage (Time-To-Live)

    For caching API responses, you want data to expire automatically. This pattern prevents stale data while improving performance.

    TTL-Based Storage

    Cache data with automatic expiration

    Try it Yourself »
    JavaScript
    // TTL-Based Storage (Time-To-Live)
    // Perfect for caching API responses
    
    function setWithTTL(key, value, ttlMs) {
      const data = {
        value,
        expiry: Date.now() + ttlMs
      };
      localStorage.setItem(key, JSON.stringify(data));
    }
    
    function getWithTTL(key) {
      const item = localStorage.getItem(key);
      if (!item) return null;
      
      try {
        const data = JSON.parse(item);
        if (Date.now() > data.expiry) {
          localStorage.removeItem(key);
          return null; // expired
        }
        return data.va
    ...

    IndexedDB: The Browser's Real Database

    IndexedDB is the production-grade solution for storing large datasets and offline application data. It supports images, audio files, documents, and complex object structures.

    Opening a Database

    Opening IndexedDB

    Learn to create and open IndexedDB databases

    Try it Yourself »
    JavaScript
    // IndexedDB is async and event-based
    // Perfect for: large datasets, offline apps, images, files
    
    const request = indexedDB.open("MyAppDB", 1);
    
    request.onupgradeneeded = (e) => {
      const db = e.target.result;
      
      // Create object stores (like tables)
      if (!db.objectStoreNames.contains("notes")) {
        db.createObjectStore("notes", { keyPath: "id" });
      }
      
      console.log("Database upgraded to version 1");
    };
    
    request.onsuccess = (e) => {
      const db = e.target.result;
      console.log("Database o
    ...

    CRUD Operations

    IndexedDB CRUD

    Create, read, update, delete with IndexedDB

    Try it Yourself »
    JavaScript
    // IndexedDB CRUD operations
    // All operations must happen inside transactions
    
    function openDB() {
      return new Promise((resolve, reject) => {
        const request = indexedDB.open("NotesDB", 1);
        
        request.onupgradeneeded = (e) => {
          const db = e.target.result;
          db.createObjectStore("notes", { keyPath: "id" });
        };
        
        request.onsuccess = () => resolve(request.result);
        request.onerror = () => reject(request.error);
      });
    }
    
    async function addNote(note) {
      const db = a
    ...

    Storing Files and Blobs

    IndexedDB can store images, audio, PDFs, and binary data — essential for PWAs and offline apps.

    Storing Files in IndexedDB

    Store images and files for offline apps

    Try it Yourself »
    JavaScript
    // Storing files and blobs in IndexedDB
    // Perfect for: offline image editors, file managers, PWAs
    
    async function saveImage(id, file) {
      const db = await openDB();
      const tx = db.transaction("images", "readwrite");
      const store = tx.objectStore("images");
      
      store.put({
        id: id,
        blob: file,
        name: file.name,
        type: file.type,
        savedAt: new Date().toISOString()
      });
      
      return new Promise((resolve, reject) => {
        tx.oncomplete = () => resolve();
        tx.onerror = () => re
    ...

    Checking Storage Availability

    Important: Safari Private Mode often breaks IndexedDB entirely. Always build with fallbacks!

    Storage Availability Check

    Detect and handle storage unavailability

    Try it Yourself »
    JavaScript
    // Always check storage availability
    // Safari Private Mode often breaks IndexedDB!
    
    function isStorageAvailable(type) {
      try {
        const storage = window[type];
        const test = "__storage_test__";
        storage.setItem(test, "1");
        storage.removeItem(test);
        return true;
      } catch (e) {
        return false;
      }
    }
    
    // Check before using
    if (isStorageAvailable("localStorage")) {
      localStorage.setItem("key", "value");
    } else {
      console.warn("localStorage not available");
      // Use in-memory fa
    ...

    Cross-Tab Communication

    localStorage can act as a lightweight messaging system between tabs. Changes trigger events in other tabs automatically.

    Cross-Tab Communication

    Sync data between browser tabs

    Try it Yourself »
    JavaScript
    // Cross-Tab Communication with Storage Events
    // localStorage changes trigger events in OTHER tabs
    
    // In Tab 1: Broadcast a logout
    function broadcastLogout() {
      localStorage.setItem("globalLogout", Date.now().toString());
    }
    
    // In Tab 2: Listen for logout
    window.addEventListener("storage", (e) => {
      if (e.key === "globalLogout") {
        console.log("Logout detected in another tab!");
        window.location.href = "/login";
      }
      
      if (e.key === "userData") {
        console.log("User data changed:",
    ...

    Offline-First Architecture

    This is the architecture behind modern productivity apps like Notion, Slack, and Linear. Save locally first, sync when online.

    Offline-First Sync

    Build offline-capable apps with sync queues

    Try it Yourself »
    JavaScript
    // Offline-First Sync Architecture
    // Used by Notion, Slack, Linear, etc.
    
    class OfflineSync {
      constructor() {
        this.queue = [];
        this.isOnline = navigator.onLine;
        
        window.addEventListener("online", () => this.processQueue());
        window.addEventListener("offline", () => this.isOnline = false);
      }
      
      async save(action) {
        // 1. Save to IndexedDB immediately (instant UI)
        await this.saveToIndexedDB(action.data);
        
        // 2. Queue sync job
        this.queue.push({
          id
    ...

    Hybrid Storage Architecture

    Professional apps combine all three storage types based on data characteristics:

    Hybrid Storage Architecture

    Combine all storage types in production apps

    Try it Yourself »
    JavaScript
    // Production Storage Architecture Example
    // Dashboard app with offline support
    
    const storageMap = {
      // localStorage: small, fast settings
      theme: "localStorage",
      language: "localStorage",
      sidebarCollapsed: "localStorage",
      recentSearches: "localStorage",
      
      // sessionStorage: tab-specific state
      currentStep: "sessionStorage",
      tabId: "sessionStorage",
      unsavedDraft: "sessionStorage",
      
      // IndexedDB: large data & offline
      tasks: "IndexedDB",
      messages: "IndexedDB",
      cachedRe
    ...

    Performance Best Practices

    Performance Best Practices

    Optimize storage for performance

    Try it Yourself »
    JavaScript
    // Performance Best Practices
    
    // ❌ BAD: Blocking the main thread on load
    const config = JSON.parse(localStorage.getItem("config"));
    heavyFunction(config); // UI freezes
    
    // ✔ GOOD: Defer to idle time
    requestIdleCallback(() => {
      const config = JSON.parse(localStorage.getItem("config"));
      heavyFunction(config);
    });
    
    // ❌ BAD: Writing on every keystroke
    input.addEventListener("input", (e) => {
      localStorage.setItem("draft", e.target.value);
    });
    
    // ✔ GOOD: Debounced writes
    let timeout;
    input.a
    ...

    Safe JSON Parsing

    Always wrap JSON.parse in try-catch to prevent app crashes from corrupted data.

    Safe JSON Parsing

    Prevent crashes from corrupted data

    Try it Yourself »
    JavaScript
    // Safe JSON Parse (prevents crashes)
    function safeParse(key, fallback = null) {
      try {
        const value = localStorage.getItem(key);
        return value ? JSON.parse(value) : fallback;
      } catch {
        console.warn("Invalid JSON for key:", key);
        localStorage.removeItem(key); // Clean up corrupted data
        return fallback;
      }
    }
    
    // Usage
    const user = safeParse("user", { name: "Guest" });
    const settings = safeParse("settings", {});
    const items = safeParse("cartItems", []);
    
    // Safe storage with 
    ...

    Common Mistakes Developers Make

    ❌ Security Mistakes

    • • Storing passwords in localStorage
    • • Storing JWT tokens (XSS can steal them)
    • • Storing PII or banking data

    ❌ Performance Mistakes

    • • Storing huge arrays in localStorage
    • • Writing on every keystroke
    • • Loading large storage synchronously

    ❌ Logic Mistakes

    • • Forgetting to JSON.stringify objects
    • • Assuming storage always exists
    • • Not handling quota errors

    ✔ Best Practices

    • • Use storage service layers
    • • Check storage availability first
    • • Use IndexedDB for large data

    Practice Exercises

    Build these projects to master Web Storage:

    1. A theme switcher using localStorage
    2. A multi-step checkout using sessionStorage
    3. A fully offline notes app using IndexedDB
    4. A custom wrapper library that unifies all three storage types
    5. A cache system that stores API responses with TTL
    6. An IndexedDB migration (version 1 → 2 → 3)
    7. A "Recently Viewed Items" tracker
    8. Cross-tab real-time sync for a shopping cart

    What You Learned

    • ✔ localStorage for persistent settings
    • ✔ sessionStorage for tab-specific state
    • ✔ IndexedDB for large datasets
    • ✔ Building storage service layers
    • ✔ TTL-based caching patterns
    • ✔ Cross-tab communication
    • ✔ Offline-first sync architecture
    • ✔ Hybrid storage design
    • ✔ Storing files and blobs
    • ✔ Safe JSON parsing

    🎉 Lesson Complete!

    You now understand how to store data client-side using localStorage, sessionStorage, and IndexedDB. Next up: Building Custom APIs.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service