Offline gespeichert heißt nicht dauerhaft gespeichert: Browser-Storage richtig prüfen
IndexedDB, Cache Storage und OPFS können Daten lange halten – aber nicht automatisch garantiert. So prüfen Sie Quoten, Persistenz, Eviction, Synchronisation und Recovery.
Eine Außendienst-App speichert Formulare offline. Ein Redaktionssystem hält Entwürfe lokal, bis die Verbindung zurück ist. Eine SaaS-Anwendung legt Dateien oder Suchindizes in IndexedDB oder im Origin Private File System ab. Im Test funktioniert alles zuverlässig – sogar nach einem Browser-Neustart.
Dann meldet ein Nutzer: „Mein Entwurf ist weg.“
Der reflexartige Satz lautet oft: „Aber wir speichern doch in IndexedDB.“
Genau darin steckt das Missverständnis. Browser-Speicher ist nicht automatisch dauerhafter Anwendungsspeicher. Die Webplattform unterscheidet zwischen best-effort und persistentem Storage. Best-effort ist der Normalfall: Daten können über Sessions hinweg erhalten bleiben, sind aber nicht gegen Quoten, Speicherknappheit, Browserregeln oder eine bewusste Löschung durch den Nutzer garantiert.
Für einfache Caches ist das völlig in Ordnung. Für den einzigen vorhandenen Vertragsentwurf, eine noch nicht synchronisierte Bestellung oder einen Offline-Arbeitsbericht ist es ein Architekturthema.
Mythos: Wenn es nach dem Reload noch da ist, ist es persistent
localStorage, IndexedDB, Cache Storage und OPFS können Daten über Reloads und Browser-Neustarts hinweg halten. Das beweist aber nur, dass sie bis jetzt nicht entfernt wurden.
Der WHATWG Storage Standard definiert eine gemeinsame Speicherarchitektur mit Quota-Schätzung und der Möglichkeit, Storage persistent zu machen. Standardmäßig arbeitet ein Origin jedoch typischerweise im best-effort-Modus. Unter Speicherknappheit kann der Browser nicht-persistente Origin-Daten entfernen.
Drei Eigenschaften sollten deshalb getrennt betrachtet werden:
- Session-langlebig: Daten überleben möglicherweise Tabs und Neustarts.
- Persistent Storage: Der Browser hat dem Origin einen stärkeren Schutz gegen automatische Löschung gewährt.
- Serverseitig gesichert: Es existiert eine zweite Kopie außerhalb dieses Browsers.
Diese drei Eigenschaften sind nicht dasselbe.
Der Speicher ist größer als nur IndexedDB
Ein Origin kann gleichzeitig IndexedDB für Datensätze, Cache Storage für Responses und Offline-Assets, OPFS für Dateien, localStorage für kleine Schlüssel-Wert-Daten und Service-Worker-bezogenen Zustand verwenden.
Für den Betrieb bedeutet das: Eine Anwendung verbraucht ihre Quote nicht nur mit Geschäftsdaten. Ein großer Offline-Cache, Vorschaubilder oder heruntergeladene Dateien konkurrieren mit wichtigen lokalen Datensätzen um begrenzten Gerätespeicher. Die Aussage „Unsere IndexedDB ist nur 30 MB groß“ ist deshalb keine vollständige Kapazitätsanalyse.
Red Flag 1: Niemand kennt Usage und Quota
Mit navigator.storage.estimate() können Anwendungen eine Schätzung der aktuellen Nutzung und der verfügbaren Quote abfragen. Das Wort Schätzung ist wichtig: Die Werte sind kein dauerhaft zugesicherter Vertrag. Quoten hängen von Browser, Gerät, freiem Speicher und Browsermodus ab und können sich ändern.
Trotzdem ist die API praktisch. Eine Offline-Anwendung, die vor einem großen Download nicht einmal prüft, ob ungefähr genug Platz vorhanden ist, behandelt einen vorhersehbaren Fehler wie ein überraschendes Ereignis.
Sinnvolle Produktlogik kann vor großen Writes die Quote prüfen, Warnschwellen definieren, entbehrliche Cache-Daten zuerst bereinigen und dem Nutzer verständlich erklären, wenn Offline-Inhalte nicht vollständig gespeichert werden können.
Red Flag 2: QuotaExceededError existiert nur in der Dokumentation
Wenn ein Write die verfügbare Quote überschreitet, können Speicheroperationen fehlschlagen. MDN dokumentiert für Technologien wie IndexedDB, Cache Storage und OPFS den Fehler QuotaExceededError.
Ein robuster Client behandelt das als echten Betriebszustand: Writes haben Fehlerbehandlung, der Datensatz bleibt als nicht gespeichert oder nicht synchronisiert erkennbar, die UI meldet keinen Erfolg vor dem abgeschlossenen Write und unwichtige Daten können kontrolliert entfernt werden.
Besonders problematisch ist das Muster: Button wird grün, Dialog schließt, asynchroner Storage-Write scheitert im Hintergrund. Technisch gab es einen Fehler; aus Nutzersicht wurde ein Versprechen gebrochen.
Red Flag 3: Kritische Daten existieren nur lokal
Browser-Storage kann genau richtig sein, wenn eine Anwendung bewusst local-first arbeitet. Aber auch local-first braucht eine Antwort auf Verlust, Konflikte und Wiederherstellung.
Für viele SaaS-Produkte gilt eine einfache Regel: Daten, deren Verlust geschäftlich weh tut, sollten nicht dauerhaft nur in einem Browserprofil existieren.
Ein Entwurf kann offline entstehen. Sobald eine Verbindung verfügbar ist, sollte eine definierte Synchronisation greifen. Dazu gehören je nach Produkt stabile lokale IDs, serverseitige Versionen, Retries, Konfliktbehandlung, idempotente Synchronisation und ein sichtbarer Sync-Status.
Ein grünes „Gespeichert“ sollte klar machen, ob damit „lokal gespeichert“ oder „auf dem Server gesichert“ gemeint ist. Diese Zustände dürfen nicht gleich aussehen, wenn ihr Risiko unterschiedlich ist.
Red Flag 4: Persistenz wird nie geprüft
Die Storage API stellt mit navigator.storage.persisted() eine Abfrage bereit, ob der Origin bereits persistenten Storage erhalten hat. Mit navigator.storage.persist() kann die Anwendung Persistenz anfragen.
Wichtig: Die Anfrage ist kein Befehl. Browser entscheiden nach eigenen Regeln, ob sie Persistenz gewähren. Die Anwendung muss also auch mit false korrekt funktionieren.
Persistent Storage sollte außerdem nicht reflexartig beim ersten Seitenaufruf angefragt werden. Sinnvoll ist die Anfrage dort, wo der Nutzer gerade eine Funktion aktiviert, deren lokale Daten tatsächlich wichtig sind – etwa „Offline verfügbar machen“ oder das Speichern eines noch nicht synchronisierten Arbeitsbereichs.
Red Flag 5: Private Browsing wurde nie getestet
Private- oder Inkognito-Modi sind ein eigener Testfall. Browser können dort andere Quoten anwenden, und lokale Daten werden üblicherweise mit dem Ende der privaten Sitzung entfernt.
Eine App, die im normalen Browserprofil sauber offline arbeitet, kann im privaten Modus weniger Speicher bekommen, Persistenz anders behandeln und nach Sitzungsende sämtliche lokalen Daten verlieren. Das muss kein Browserfehler sein. Es wird zum Produktfehler, wenn die Oberfläche trotzdem dauerhafte Offline-Verfügbarkeit verspricht.
Cache und unersetzliche Daten brauchen unterschiedliche Priorität
Ein heruntergeladenes Vorschaubild kann neu erzeugt werden. Ein noch nicht synchronisierter Entwurf möglicherweise nicht. Trotzdem landen beide oft im selben impliziten Risikomodell: „liegt lokal“.
Hilfreicher ist eine Datenklassifikation:
- Regenerierbar: Bundles, Bilder, API-Caches, Suchindizes. Verlust kostet Zeit oder Bandbreite, aber keine fachlichen Daten.
- Synchronisiert: Lokale Kopien von Daten, die bereits zuverlässig auf dem Server liegen.
- Noch nicht synchronisiert: Entwürfe, Eingaben, Aufnahmen oder Arbeitsstände, die nur auf diesem Gerät existieren. Diese Klasse verdient höchste Priorität und schnelle Synchronisation.
- Bewusst lokal: Daten, die absichtlich nicht zum Server gehen. Wenn Verlust nicht akzeptabel ist, braucht das Produkt eine explizite Export-, Backup- oder Recovery-Strategie.
Diese Einteilung ist für Architekturentscheidungen oft hilfreicher als die Frage „IndexedDB oder OPFS?“.
Browser unterscheiden sich – deshalb ist eine feste GB-Zahl die falsche Spezifikation
WebKit dokumentiert ein quotenbasiertes Modell, das sich am Gerätespeicher orientiert und best-effort Origins unter bestimmten Bedingungen entfernen kann. Chrome und andere Browser verwenden eigene Quotenmodelle. MDN dokumentiert diese Unterschiede browserübergreifend.
Die robuste Anforderung lautet daher nicht: „Wir haben immer 5 GB.“ Sondern: Wir können die aktuelle Quote schätzen, erkennen Schreibfehler, können entbehrliche Daten freigeben, haben für kritische Daten eine Recovery-Strategie und lassen Offline-Funktionen verständlich degradieren, wenn Speicher fehlt.
Was ein sinnvoller Storage-Audit testet
Ein echter Audit geht über „Ist IndexedDB vorhanden?“ hinaus. Er prüft:
- Dateninventar: Was liegt in IndexedDB, Cache Storage, OPFS und
localStorage? Was ist regenerierbar, synchronisiert oder einzigartig? - Quote und Wachstum: Wie viel Speicher wird nach einem Tag, einem Monat oder hundert Offline-Datensätzen belegt?
- Fehlerpfade: Was passiert bei
QuotaExceededError, abgebrochenen Writes oder fehlendem Speicher? Bleibt die UI ehrlich? - Persistenzstatus: Wird
persisted()geprüft? Gibt es einen sinnvollen Moment fürpersist()? Funktioniert die App trotzdem, wenn Persistenz nicht gewährt wird? - Synchronisation: Was passiert nach langem Offline-Betrieb, mehreren Geräten oder serverseitigen Änderungen?
- Löschung und Recovery: Startet die Anwendung nach „Website-Daten löschen“, Profilwechsel oder Eviction sauber neu?
- Migrationen: Funktionieren neue Releases mit einer alten, bereits gefüllten IndexedDB und nicht nur mit einem frischen Entwicklerprofil?
Testen Sie Verlust absichtlich
Der wertvollste Storage-Test ist nicht „Reload und Daten sind noch da“. Testen Sie fast vollen Speicher, große Offline-Datenmengen, gewährte und verweigerte Persistenz, ein privates Fenster, gelöschte Website-Daten, Offline-Writes mit späterem Reconnect und ein Release-Update mit bestehender lokaler Datenbank.
Das Ziel ist nicht, jede Browserentscheidung zu verhindern. Das geht nicht. Das Ziel ist, Datenverlust nicht mit Anwendungschaos zu verwechseln.
Was Website-Pflichtencheck prüfen würde
Bei einer Web-App mit lokaler Speicherung würde Website-Pflichtencheck die tatsächlichen Storage-Mechanismen, Datenklassen, Nutzung und Quote, Persistenzstatus, Fehlerbehandlung, Offline-Synchronisation, Cache-Bereinigung, private Browsermodi, Schema-Upgrades und Recovery-Verhalten prüfen.
Besonders relevant ist das für Anwendungen, die „offlinefähig“, „Entwürfe werden automatisch gespeichert“ oder „später synchronisieren“ versprechen. Solche Aussagen sind keine reine UX-Texte. Dahinter steckt eine technische Haltbarkeitsgarantie, die sich testen lassen muss.
Browser-Storage ist leistungsfähig. IndexedDB, Cache Storage und OPFS ermöglichen sehr robuste Webanwendungen. Aber lokal vorhanden ist nicht automatisch dauerhaft gesichert. Wer diese Grenze bewusst modelliert, bekommt robustere Technik und eine ehrlichere Oberfläche: Nutzer wissen, was nur auf diesem Gerät liegt, was synchronisiert wurde und was nach einem Fehler wiederhergestellt werden kann.