IndexedDB vs. localStorage: Welchen Browserspeicher du nutzen solltest
IndexedDB vs. localStorage
IndexedDB vs. localStorage: Limits, Tempo, Einsatzzweck | We.Inc
IndexedDB und localStorage im direkten Vergleich: Größenlimits je Browser, synchron vs. asynchron, was jeder speichern kann, plus eine Live-Demo, die eine Notiz in beiden speichert.
Nimm localStorage für ein paar kleine Einstellungen: Es speichert nur Strings, etwa 5 MiB pro Origin, und jeder Aufruf blockiert die Seite, bis er fertig ist. Nimm IndexedDB für echte Daten: Es ist asynchron, transaktional, speichert Objekte, Datumswerte und Dateien, und sein Kontingent ist ein Anteil der Festplatte. Die Demo unten schreibt eine Notiz in beide.
Die Kurzfassung
Frage
localStorage
IndexedDB
Was kann gespeichert werden?
Nur Strings
Alles, was der Structured-Clone-Algorithmus kopiert, auch Blob und File
Größe
Bis zu 5 MiB pro Origin
Ein Anteil des freien Speicherplatzes, vom Browser festgelegt
Blockiert die Seite?
Ja, jeder Aufruf ist synchron
Nein, Ergebnisse kommen über Events oder Promises
Transaktionen und Indizes
Nein
Ja
In einem Web Worker nutzbar
Nein, es ist eine Eigenschaft von window
Ja
Am besten für
Theme, zuletzt geöffneter Tab, ein Entwurfs-String
Offline-Daten, Caches, Dateien, alles, was du abfragst
Beide APIs behalten Daten im Browser des Besuchers, nachdem der Tab geschlossen wurde, und beide sind auf den Origin der Seite beschränkt. Der Unterschied liegt im Gewicht. localStorage ist eine winzige synchrone String-Map, die du in einer Minute lernst; IndexedDB ist eine kleine Datenbank mit Versionen, Object Stores und Transaktionen. Diese Seite zeigt die echten Limits aus der Dokumentation und lässt dich sehen, was jede API zurückgibt.
Gib eine Notiz ein und drücke In beiden speichern. Die Seite schreibt sie als JSON-Text in localStorage und als echtes Objekt in einen IndexedDB-Object-Store.
Drücke Zurücklesen. Das Ergebnisfeld zeigt den Typ, den jede API zurückgegeben hat: einen String aus localStorage, ein Objekt mit funktionierendem Date aus IndexedDB.
Drücke Kontingent prüfen, um navigator.storage.estimate() zu fragen, wie viel dieser Origin belegt und belegen darf. Die Zahlen sind Schätzungen.
Drücke Demo-Daten löschen, um den Demo-Schlüssel zu entfernen und die Demo-Datenbank zu löschen. Nichts verlässt dein Gerät.
Pack localStorage.setItem in ein try...catch. Ein voller Speicher wirft QuotaExceededError, und manche Datenschutzeinstellungen werfen beim ersten Zugriff SecurityError.
Speichere in localStorage die Ausgabe von JSON.stringify und parse sie beim Lesen. Datumswerte kommen als Strings zurück, du musst sie also selbst umwandeln.
Für IndexedDB macht ein kleiner Wrapper wie idb oder Dexie aus dem Request-und-Event-Stil Promises und spart viel Boilerplate.
Rufe navigator.storage.persist() nur für Daten auf, deren Verlust die Person ärgern würde, etwa Offline-Dokumente. Sonst darf der Browser sie bei Speicherknappheit entfernen.
Bewahre niemals Geheimnisse oder Session-Tokens in einem der beiden Speicher auf. Jedes Skript auf der Seite kann sie lesen.
Häufige Fragen
Wie viel passt in localStorage?
MDN dokumentiert ein Limit von 5 MiB für Local Storage und 5 MiB für Session Storage pro Origin, insgesamt 10 MiB. Da Werte UTF-16-Strings sind, passen eventuell weniger Zeichen hinein, als du erwartest. Wird das Limit überschritten, wird ein QuotaExceededError geworfen.
Wie viel passt in IndexedDB?
Das hängt vom Browser und vom Datenträger ab. Chromium-Browser erlauben einem Origin bis zu 60 % der gesamten Festplattengröße. Firefox erlaubt im Best-Effort-Modus den kleineren Wert von 10 % der Festplatte oder 10 GiB pro Site-Gruppe. Die Safari-Browser-App erlaubt etwa 60 % der Festplatte. Mit navigator.storage.estimate() liest du den echten Wert aus.
Ist IndexedDB schneller als localStorage?
Für einen einzelnen winzigen Wert ist localStorage meist schneller geschrieben und läuft schnell genug. Das Problem: Es ist synchron, große Lese- und Schreibvorgänge frieren also den Main Thread ein. IndexedDB erledigt die Arbeit außerhalb des Hauptablaufs und meldet sich, wenn es fertig ist. So bleiben Scrollen und Tippen flüssig.
Kann der Browser meine IndexedDB-Daten löschen?
Ja. Speicher ist standardmäßig Best-Effort, der Browser darf also die Daten eines Origins entfernen, wenn der Speicherplatz knapp wird. Ein Aufruf von navigator.storage.persist() wechselt in den persistenten Modus, in dem nur die Person selbst die Daten löschen kann. Firefox zeigt dafür eine Berechtigungsabfrage; Chrome und Safari entscheiden anhand davon, wie die Person die Website nutzt.
Sollte ich localStorage für ein Login-Token verwenden?
Nein. Jedes Skript auf der Seite, auch ein eingeschleustes, kann localStorage und IndexedDB lesen. Bewahre Session-Kennungen in Cookies mit HttpOnly, Secure und SameSite auf, die Skripte auf der Seite nicht lesen können.
Warum synchron wichtig ist
Wenn Code localStorage.getItem aufruft, führt der Browser kein anderes JavaScript aus, bis der Wert von der Festplatte zurückkommt. Bei einem Theme-Namen merkt das niemand. Bei einigen Megabyte JSON, die bei jedem Seitenaufruf geparst werden, zeigt es sich als Pause, bevor die Seite auf Tippen reagiert.
IndexedDB gibt sofort ein Request-Objekt zurück und löst später success oder error aus. Diese Form bedeutet mehr Code, weshalb die meisten Projekte einen Promise-Wrapper nutzen, aber sie hält die Seite nie als Geisel.
Strings vs. Structured Clone
localStorage macht aus allem Text. Speicherst du die Zahl 3, liest du den String "3" zurück; speicherst du ein Objekt ohne JSON.stringify, liest du "[object Object]" zurück.
IndexedDB kopiert Werte mit dem Structured-Clone-Algorithmus, ein Date bleibt also ein Date, eine Map bleibt eine Map, und ein Blob oder File kann unverändert gespeichert werden. Genau das macht es geeignet für Offline-Bilder, aufgenommenes Audio oder Entwürfe mit Anhängen.
Eine einfache Faustregel
Passen die Daten in eine kurze Zeile und liest du sie einmal beim Start, ist localStorage in Ordnung. Willst du sie durchsuchen, zählen, seitenweise durchblättern, Binärdateien darin speichern oder sie aus einem Service Worker aktualisieren, nimm IndexedDB.
Daten auf dem Server sind eine dritte Option, die oft beide schlägt: Erwartet die Person, dasselbe auf einem anderen Gerät zu sehen, gehören die Daten in deine Datenbank, und der Browserspeicher dient nur als Cache.
Speicherlimits nach Browser
Werte laut der MDN-Seite zu Speicherkontingenten. IndexedDB, die Cache API und das Origin Private File System teilen sich dasselbe Kontingent.
Kontingent pro Origin
Browser
localStorage
IndexedDB (Best-Effort)
IndexedDB (persistent)
Chrome, Edge und andere Chromium-Browser
5 MiB
Bis zu 60 % der gesamten Festplatte
Bis zu 60 % der gesamten Festplatte
Firefox
5 MiB
Der kleinere Wert von 10 % der Festplatte oder 10 GiB pro Site-Gruppe
Bis zu 50 % der Festplatte, maximal 8 TiB
Safari-Browser-App
5 MiB
Etwa 60 % der gesamten Festplatte
Etwa 60 % der gesamten Festplatte
Apps, die Webinhalte einbetten (WebKit)
5 MiB
Etwa 15 % der gesamten Festplatte
Etwa 15 % der gesamten Festplatte
Derselbe Speichervorgang in beiden APIs
localStorage: stringify, absichern, parsen
Das try...catch fängt einen vollen oder blockierten Speicher ab. Das Datum muss nach dem Parsen von Hand neu erzeugt werden.
IndexedDB: öffnen, upgraden, in einer Transaktion schreiben
onupgradeneeded läuft beim ersten Mal und jedes Mal, wenn die Versionsnummer steigt; nur dort kannst du Object Stores anlegen.
Frag, wie viel Platz du hast, und bitte darum, ihn zu behalten
estimate() gibt ungefähre Byte-Zahlen zurück. persist() wird mit true aufgelöst, wenn der Browser persistenten Speicher gewährt hat.
Eine Notiz in beiden Speichern sichern
Diese Demo läuft nur in deinem Browser. Sie schreibt unter dem Schlüssel we-demo-note und in eine Datenbank namens we-demo-db, und der Löschen-Button entfernt beides.
Zu speichernde Notiz
Am Freitag den Drucker anrufen
In beiden speichern
Zurücklesen
Kontingent prüfen
Demo-Daten löschen
Noch nichts gelesen. Speichere eine Notiz und drücke dann Zurücklesen.
localStorage hat zurückgegeben
IndexedDB hat zurückgegeben
Typ: {v}
savedAt ist ein Date: {v}
Nichts gespeichert
Die Notiz wurde in localStorage und IndexedDB gespeichert.
Demo-Schlüssel und Datenbank wurden entfernt.
Dieser Origin belegt etwa {n} MB von ungefähr {v} MB verfügbarem Speicher.
Dieser Browser bietet navigator.storage.estimate() nicht an.
Speichern ist in diesem Browser fehlgeschlagen: {v}