The matrix-js-sdk separates concerns between two kinds of storage:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/matrix-org/matrix-js-sdk/llms.txt
Use this file to discover all available pages before exploring further.
- Sync store — rooms, timelines, account data, filters, and the current sync token. Configured via the
storeoption increateClient(). - Crypto store — end-to-end encryption session data (Olm/Megolm sessions, device keys). Configured via
cryptoStore, or managed automatically byinitRustCrypto().
MemoryStore (default)
MemoryStore keeps all data in JavaScript memory. It is created automatically when no store is supplied to createClient().
What MemoryStore stores
Internally,MemoryStore holds:
Optional localStorage integration
MemoryStore accepts a localStorage option. When provided, filter IDs are persisted across page reloads (keyed with the prefix mxjssdk_memory_filter_), which avoids re-uploading the sync filter on every session:
Passing
localStorage to MemoryStore persists filter IDs only — not rooms, timelines, or the sync token. After a page reload the client performs a full sync from the server.When to use MemoryStore
Suitable for
- Node.js scripts and bots
- Short-lived sessions (automated tasks)
- Server-side rendering where IndexedDB is unavailable
- Testing and development
Not suitable for
- Browser apps where users expect fast startup after reload
- Clients that must survive page refreshes without a full re-sync
- Applications managing large numbers of rooms
IndexedDBStore
IndexedDBStore extends MemoryStore. It holds all data in memory but periodically flushes the full sync response to an IndexedDB database (every 5 minutes by default). On startup, calling store.startup() loads the previously persisted state, so the first meaningful sync comes from disk rather than the server.
Constructor options
| Option | Type | Description |
|---|---|---|
indexedDB | IDBFactory | The IndexedDB interface, e.g. window.indexedDB |
localStorage | Storage | Used to persist filter IDs (optional) |
dbName | string | Database name. Use the same name across sessions to reuse persisted data |
workerFactory | () => Worker | Optional factory to run IDB transactions in a Web Worker |
Store degradation and the degraded event
If an IndexedDB operation fails on a non-critical path, the store falls back to purely in-memory operation and emits a degraded event:
When to use IndexedDBStore
Suitable for
- Browser-based Matrix clients
- Apps where users reload the page and expect fast startup
- Clients managing many rooms where a full re-sync is expensive
Not suitable for
- Node.js (no browser
indexedDB) - Environments with very limited storage quotas
- Multiple
MatrixClientinstances sharing the same database (causes corruption)
Choosing a store
- Browser app
- Node.js / bot
Browser storage limits and behaviour
The notes below are based on observed behaviour in Firefox and Chrome (seedocs/storage-notes.md in the SDK repository).
Quota limits
Quota limits
Browsers measure quota in terms of on-disk space (not raw data size), so compressible data may fit within quota even when the raw size appears to exceed it.When quota is exhausted:
- Chrome — IndexedDB startup may fail with
AbortError; near the limit,QuotaExceededErroris raised. - Firefox — First failure is
QuotaExceededError; subsequent writes may raise misleading errors likeInvalidStateError. The database can become effectively read-only until it is reopened.
Cache eviction
Cache eviction
Under storage pressure the browser may delete IndexedDB for an origin.
localStorage is handled separately by browsers and is not evicted when IndexedDB is deleted.This is why MemoryStore (with localStorage) and IndexedDBStore both persist filter IDs in localStorage — they survive eviction.Persistent storage
Persistent storage
Use the Storage Standard Chrome grants this automatically based on user engagement criteria. Firefox shows a permission prompt.
navigator.storage.persist() API to request persistent storage that the browser will not evict automatically:Storage estimation
Storage estimation
Use Note: Firefox returns
navigator.storage.estimate() to check remaining quota:0 for usage when the site has persistent storage.Checking whether a database already exists
IndexedDBStore exposes a static helper to check whether a named database exists before trying to open it:
Crypto store versus sync store
The crypto store is separate from the sync store:| Sync store | Crypto store | |
|---|---|---|
| Configured via | store in createClient() | cryptoStore in createClient(), or auto-managed by initRustCrypto() |
| Holds | Rooms, timelines, account data, sync token | Olm/Megolm sessions, device keys, cross-signing keys |
| Default | MemoryStore | IndexedDB in browser, in-memory in Node.js |
| Class | MemoryStore / IndexedDBStore | CryptoStore (legacy) / Rust crypto (current) |
initRustCrypto() after creating the client. The Rust crypto backend manages its own IndexedDB store automatically: