How does Android OkHttp cache work?

Life without caching!

Caching is a very interesting topic in software engineering.


Let’s imagine that the Facebook app keeps loading the new feed from scratch every time we pull our finger or Google Photos app takes 10s to regenerate all the photo thumbnails every time we open. That kind of experience would kill our user’s happiness!

We are all good engineers and we really care about user experience.
So in this topic, let’s narrow down that big caching topic into OkHttp cache.


This simple diagram describes the whole complex story behind:)

OkHttp caching mechanism

Quick questions and answers.

We will not cover everything about OkHttp cache because it just follows the Http caching mechanism. If you have no idea about that, read it first: No rush :)

1. How to enable the cache?

int cacheSize = 10 * 1024 * 1024; // 10MB
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.cache(new Cache(context.getCacheDir(), cacheSize)

2. How can I make it works?

Do nothing! Yeah. It automatically parses the cache-related header from the server and stores the response into the cache dir. Next time, when we send the request, it will automatically append the corresponding header for us.

For example, if the server responses:

Date:Wed, 29 Mar 2017 10:54:09 GMT
Last-Modified:Wed, 29 Mar 2017 03:25:27 GMT

then next time, OkHttp will set the request header to:

If-Modified-Since:Wed, 29 Mar 2017 03:25:27 GMT

More info:

3. How to make it works offline?

If the server gives max-age which tells OkHttp that it can cache the response and use it offline then it will just work.

If max-age is not available or it expires but you still want to use local data, you can fore use it by set request like this:

new Request.Builder().cacheControl(CacheControl.FORCE_CACHE)

Then the flow will become:

Force cache

More generally, if you always want to use local cache whenever there is no Internet:

public class ForceCacheInterceptor implements Interceptor {
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
if (!NetworkUtils.internetAvailable()) {

return chain.proceed(;
okHttpClient.addInterceptor(new ForceCacheInterceptor());

Note that this interceptor must be added as an application interceptor. If we add it as a network interceptor, it will have no chance to be triggered.

4. Is it a good idea to use OkHttp for data storing? Just use ‘FORCE_CACHE’ and we will always get the cached data?

It’s a bad idea.

Those are fundamentally different and should be treated differently​. Data should always available, while cache may not.

E.g. login token should be stored, while new feeds should be cached.

Stop for a while, enjoy coffee and think about that…

More details doc is here:

5. How to decide whether we need the server to validate the cache?

This is done using max-age which tells how long the response can be cached.

For example, you are refreshing your Facebook setting page which has a list of settings. So, that list should stay unchanged for quite sometimes. So instead of return the same response every time, the server can just say max-age=3600 and for all the subsequence requests in the next 1 hour (3600 seconds), the client can just use the local cached data.

6. How does the server decide whether the client can use its cached data or not?

There can be done in a few ways. Basically:

  • The client will send out something like timestamp or Etag of the last request
  • The server can then check if there is some data has changed in during that period of time or not.
  • If nothing has changed, the server can just give a special code (304 -not modified) without sending the whole same response again. And we can save some bandwidth of in this case.

One example is the Gmail app, because the client has no way to know if there are new emails every time the user refreshes, so it can’t just simply use the cached data. What it always does is to send out the last Etag to tell the server what was the last time the user checked their inbox. Then if there is no new email, the server just tells the client to use its cache to display the same email list.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade