Firebase Disk Caching Across Reboots
This is the third article in our series on Firebase. Here are some more posts in the series:
How to Connect to Multiple Firebase Databases with an Android App
Firebase Connection Management
There is a lot of incomplete and misleading information on how to use Firebase's disk caching feature, which allows for data persistence across network outages and reboots. Google's documentation on this Firebase capability, and on how to leverage it, is spotty, and in some places actively misleading. In the same vein, there is misinformation aplenty on the subject elsewhere on the Internet.
Since SDG uses Firebase for several products which often operate in low-reliability power and network environments, solving this problem is important to us. As such, we decided to compile our findings here, to add clarity to the topic of Firebase caching across reboots.
Enabling Disk Caching
Enabling disk caching is straightforward. Immediately after getting a FirebaseDatabase object from FirebaseDatabase.getInstance(FirebaseApp), call setPersistenceEnabled(true) on it. This enables disk persistence in general, but doesn't necessarily ensure the information you want will be available.
Next, get a DatabaseReference which encapsulates the data you want to keep stored locally, and call keepSynced(true) on it. Firebase disk caching is only guaranteed to keep a reference in the disk cache if that reference has a watcher on it. keepSynced ensures that a dummy watcher is in place so that Firebase retains the data located at the reference and its children. It also ensures that such data does not pass out of the cache.
FirebaseApp fbApp = … //get a firebase app instance FirebaseAuth fbAuth = FirebaseAuth.getInstance(fbApp); fbDatabase = FirebaseDatabase.getInstance(fbApp); // setPersistenceEnabled(true) tells firebase to write all synced data to local disk, which ensures data access across reboots--even if the network is down. fbDatabase.setPersistenceEnabled(true); // Even if this fails, disk-cached references will be available for reading, and writes will be persisted to disk. fbAuth.signIn… DatabaseReference refOfInterest = fbDatabase.getReference("reference"); // refOfInterest will be kept in the disk cache for offline reads. refOfInterest.keepSynced()
Note that authentication is optional when using the disk cache—it's not required to read from cached references, or write to any reference.
The Firebase disk cache has two parts: a 10mb-by-default least-recently-used cache, and the cache containing watched references. There is no strict limit on the size of the watched references cache; the 10mb LRU cache contains the most recent 10mb of data not in the watched references cache.
Reading From Cache
Reading from the Firebase cache requires no code changes to the database read code. (Uncached references may show up in the LRU cache, or may not show up at all, so you will want to be careful to read from cached references only when not authenticated/online.) Database reads to synchronized references will succeed even without valid authentication, though, allowing you to use the cached data.
Writing To Cache
Writing to cache also requires no changes to your database code. With persistence enabled, offline writes go to the cache, where they persist until connectivity is restored. In the same way as reads, authentication will be unavailable, but write operations will succeed regardless of authentication state.
Contrary to the Firebase documentation, writes to the disk cache persist not only across app restarts but even device restarts. Not only do cached writes persist across brief outages, but even, in our testing, across a weekend.
SDG first integrated Firebase into the project for which the above research took place on the strength of Firebase's marketing copy. In particular, the offline database capability precisely matched our requirements: to seamlessly sync data between a remote device on a spotty network and a back end, caching locally until the connection is usable.
Although the Firebase documentation preaches doom and gloom about caching, and in many places fails to distinguish between in-memory caching and on-disk caching. It's been our experience, after we ran our experiments and figured this out, that this is an instance in which the marketing copy is actually nearer the truth, at least for on-disk caching, than the documentation.