Stay organized with collectionsSave and categorize content based on your preferences.
Cloud Firestoresupports offline data persistence. This feature caches a copy
of theCloud Firestoredata that your app is actively using, so your app
can access the data when the device is offline. You can write, read, listen to,
and query the cached data. When the device comes back online,Cloud Firestoresynchronizes any local changes made by your app to theCloud Firestorebackend.
To use offline persistence, you don't need to make any changes to the code that
you use to accessCloud Firestoredata. With offline persistence enabled,
theCloud Firestoreclient library automatically manages online and
offline data access and synchronizes local data when the device is back online.
Configure offline persistence
When you initializeCloud Firestore, you can enable or disable
offline persistence:
For Android and Apple platforms, offline persistence is enabled by default. To disable
persistence, set thePersistenceEnabledoption tofalse.
For the web, offline persistence is disabled by default. To enable
persistence, call theenablePersistencemethod.Cloud Firestore's cache
isn't automatically cleared between sessions. Consequently, if your web app
handles sensitive information, make sure to ask the user if they're on a trusted
device before enabling persistence.
Web
// Memory cache is the default if no config is specified.initializeFirestore(app);// This is the default behavior if no persistence is specified.initializeFirestore(app,{localCache:memoryLocalCache()});// Defaults to single-tab persistence if no tab manager is specified.initializeFirestore(app,{localCache:persistentLocalCache(/*settings*/{})});// Same as `initializeFirestore(app, {localCache: persistentLocalCache(/*settings*/{})})`,// but more explicit about tab management.initializeFirestore(app,{localCache:persistentLocalCache(/*settings*/{tabManager:persistentSingleTabManager()})});// Use multi-tab IndexedDb persistence.initializeFirestore(app,{localCache:persistentLocalCache(/*settings*/{tabManager:persistentMultipleTabManager()})});
Web
firebase.firestore().enablePersistence().catch((err)=>{if(err.code=='failed-precondition'){// Multiple tabs open, persistence can only be enabled// in one tab at a a time.// ...}elseif(err.code=='unimplemented'){// The current browser does not support all of the// features required to enable persistence// ...}});// Subsequent queries will use persistence, if it was enabled successfully
Note:This product is not available on watchOS and App Clip targets.
letsettings=FirestoreSettings()// Use memory-only cachesettings.cacheSettings=MemoryCacheSettings(garbageCollectorSettings:MemoryLRUGCSettings())// Use persistent disk cache, with 100 MB cache sizesettings.cacheSettings=PersistentCacheSettings(sizeBytes:100*1024*1024asNSNumber)// Any additional options// ...// Enable offline data persistenceletdb=Firestore.firestore()db.settings=settings
Note:This product is not available on watchOS and App Clip targets.
FIRFirestoreSettings*settings=[[FIRFirestoreSettingsalloc]init];// Use memory-only cachesettings.cacheSettings=[[FIRMemoryCacheSettingsalloc]initWithGarbageCollectorSettings:[[FIRMemoryLRUGCSettingsalloc]init]];// Use persistent disk cache (default behavior)// This example uses 100 MB.settings.cacheSettings=[[FIRPersistentCacheSettingsalloc]initWithSizeBytes:@(100*1024*1024)];// Any additional options// ...// Enable offline data persistenceFIRFirestore*db=[FIRFirestorefirestore];db.settings=settings;
valsettings=firestoreSettings{// Use memory cachesetLocalCacheSettings(memoryCacheSettings{})// Use persistent disk cache (default)setLocalCacheSettings(persistentCacheSettings{})}db.firestoreSettings=settings
FirebaseFirestoreSettingssettings=newFirebaseFirestoreSettings.Builder(db.getFirestoreSettings())// Use memory-only cache.setLocalCacheSettings(MemoryCacheSettings.newBuilder().build())// Use persistent disk cache (default).setLocalCacheSettings(PersistentCacheSettings.newBuilder().build()).build();db.setFirestoreSettings(settings);
// Apple and Androiddb.settings=constSettings(persistenceEnabled:true);// Webawaitdb.enablePersistence(constPersistenceSettings(synchronizeTabs:true));
When persistence is enabled,Cloud Firestorecaches every document
received from the backend for offline access.Cloud Firestoresets a
default threshold for cache size. After exceeding the default,Cloud Firestoreperiodically attempts to clean up older, unused
documents. You can configure a different cache size threshold
or disable the clean-up process completely:
Note:This product is not available on watchOS and App Clip targets.
// The default cache size threshold is 100 MB. Configure "cacheSizeBytes"// for a different threshold (minimum 1 MB) or set to "FirestoreCacheSizeUnlimited"// to disable clean-up.letsettings=Firestore.firestore().settings// Set cache size to 100 MBsettings.cacheSettings=PersistentCacheSettings(sizeBytes:100*1024*1024asNSNumber)Firestore.firestore().settings=settings
Note:This product is not available on watchOS and App Clip targets.
// The default cache size threshold is 100 MB. Configure "cacheSizeBytes"// for a different threshold (minimum 1 MB) or set to "kFIRFirestoreCacheSizeUnlimited"// to disable clean-up.FIRFirestoreSettings*settings=[FIRFirestorefirestore].settings;// Set cache size to 100 MBsettings.cacheSettings=[[FIRPersistentCacheSettingsalloc]initWithSizeBytes:@(100*1024*1024)];[FIRFirestorefirestore].settings=settings;
// The default cache size threshold is 100 MB. Configure "setCacheSizeBytes"// for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED"// to disable clean-up.valsettings=FirebaseFirestoreSettings.Builder().setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED).build()db.firestoreSettings=settings
Java
// The default cache size threshold is 100 MB. Configure "setCacheSizeBytes"// for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED"// to disable clean-up.FirebaseFirestoreSettingssettings=newFirebaseFirestoreSettings.Builder().setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED).build();db.setFirestoreSettings(settings);
While the device is offline, if you have enabled offline persistence, your
listeners will receive listen events when the locally cached data changes. You
can listen to documents, collections, and queries.
To check whether you're receiving data from the server or the cache, use thefromCacheproperty on theSnapshotMetadatain your snapshot event. IffromCacheistrue, the data came from the cache and might be stale or
incomplete. IffromCacheisfalse, the data is complete and current with the
latest updates on the server.
By default, no event is raised ifonlytheSnapshotMetadatachanged. If you
rely on thefromCachevalues, specify theincludeMetadataChangeslisten
option when you attach your listen handler.
Web
import{collection,onSnapshot,where,query}from"firebase/firestore";constq=query(collection(db,"cities"),where("state","==","CA"));onSnapshot(q,{includeMetadataChanges:true},(snapshot)=>{snapshot.docChanges().forEach((change)=>{if(change.type==="added"){console.log("New city: ",change.doc.data());}constsource=snapshot.metadata.fromCache?"local cache":"server";console.log("Data came from "+source);});});
db.collection("cities").where("state","==","CA").onSnapshot({includeMetadataChanges:true},(snapshot)=>{snapshot.docChanges().forEach((change)=>{if(change.type==="added"){console.log("New city: ",change.doc.data());}varsource=snapshot.metadata.fromCache?"local cache":"server";console.log("Data came from "+source);});});
Note:This product is not available on watchOS and App Clip targets.
// Listen to metadata updates to receive a server snapshot even if// the data is the same as the cached data.db.collection("cities").whereField("state",isEqualTo:"CA").addSnapshotListener(includeMetadataChanges:true){querySnapshot,erroringuardletsnapshot=querySnapshotelse{print("Error retreiving snapshot:\(error!)")return}fordiffinsnapshot.documentChanges{ifdiff.type==.added{print("New city:\(diff.document.data())")}}letsource=snapshot.metadata.isFromCache?"local cache":"server"print("Metadata: Data fetched from\(source)")}
Note:This product is not available on watchOS and App Clip targets.
// Listen to metadata updates to receive a server snapshot even if// the data is the same as the cached data.[[[dbcollectionWithPath:@"cities"]queryWhereField:@"state"isEqualTo:@"CA"]addSnapshotListenerWithIncludeMetadataChanges:YESlistener:^(FIRQuerySnapshot*snapshot,NSError*error){if(snapshot==nil){NSLog(@"Error retreiving snapshot: %@",error);return;}for(FIRDocumentChange*diffinsnapshot.documentChanges){if(diff.type==FIRDocumentChangeTypeAdded){NSLog(@"New city: %@",diff.document.data);}}NSString*source=snapshot.metadata.isFromCache?@"local cache":@"server";NSLog(@"Metadata: Data fetched from %@",source);}];
If you get a document while the device is offline,Cloud Firestorereturns data from the cache.
When querying a collection, an empty result is returned if there are no cached
documents. When fetching a specific document, an error is returned instead.
Query offline data
Querying works with offline persistence. You can retrieve the results of queries
with either a direct get or by listening, as described in the preceding
sections. You can also create new queries on locally persisted data while the
device is offline, but the queries will initially run only against the cached
documents.
Configure offline query indexes
By default, the Firestore SDK scans all documents in a collection in its
local cache when executing offline queries. With this default behavior, offline
query performance can suffer when users are offline for long periods of time.
With persistent cache enabled, you can improve the performance of offline
queries by allowing the SDK to create local query indexes automatically.
Automatic indexing is disabled by default. Your app must enable
automatic indexing each time it starts. Control whether automatic indexing is
enabled as shown below.
Swift
ifletindexManager=Firestore.firestore().persistentCacheIndexManager{// Indexing is disabled by defaultindexManager.enableIndexAutoCreation()}else{print("indexManager is nil")}
Objective-C
PersistentCacheIndexManager*indexManager=[FIRFirestorefirestore].persistentCacheIndexManager;if(indexManager){// Indexing is disabled by default[indexManagerenableIndexAutoCreation];}
Kotlin
// return type: PersistentCacheManager?Firebase.firestore.persistentCacheIndexManager?.apply{// Indexing is disabled by defaultenableIndexAutoCreation()}?:println("indexManager is null")
Java
// return type: @Nullable PersistentCacheIndexManagerPersistentCacheIndexManagerindexManager=FirebaseFirestore.getInstance().getPersistentCacheIndexManager();if(indexManager!=null){// Indexing is disabled by defaultindexManager.enableIndexAutoCreation();}// If not check indexManager != null, IDE shows warning: Method invocation 'enableIndexAutoCreation' may produce 'NullPointerException'FirebaseFirestore.getInstance().getPersistentCacheIndexManager().enableIndexAutoCreation();
Once automatic indexing is enabled, the SDK evaluates which collections have
a large number of cached documents and optimizes performance of local queries.
The SDK provides a method for deleting query indexes.
Disable and enable network access
You can use the method below to disable network access for yourCloud Firestoreclient. While network access is disabled, all snapshot
listeners and document requests retrieve results from the cache. Write
operations are queued until network access is re-enabled.
Web
import{disableNetwork}from"firebase/firestore";awaitdisableNetwork(db);console.log("Network disabled!");// Do offline actions// ...
db.disableNetwork().addOnCompleteListener(newOnCompleteListener<Void>(){@OverridepublicvoidonComplete(@NonNullTask<Void>task){// Do offline things// ...}});
db.enableNetwork().addOnCompleteListener(newOnCompleteListener<Void>(){@OverridepublicvoidonComplete(@NonNullTask<Void>task){// Do online things// ...}});
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[],[],null,[]]