URLCache – Default size is not enough

Even though networks are getting faster every day, the amount of data transferred between your device and the cloud is also increasing. Here at Just Eat, we always aim to write reliable, and efficient code that results in fast, problem free transactions.

Having a good caching strategy is an essential part of this. Having an effective cache could help:

  • 🙂 improve the user experience, by making the app faster and by saving battery life 🔋
  • 🌱 save energy by reducing the amount of overall network traffic
  • 💰 save money on the infrastructure, because the backend load will be reduced without any product change.

iOS has built-in support for HTTP caching, so you might think the work has already been done for you. But if you look closely, you might start wondering why some of your network calls get executed every time. If your app is doing that, a simple reason could be because there isn’t enough space to cache the response so make sure you check your URL shared cache size!

Investigating the problem and understanding the solution:

Let’s go a bit deeper.

URLCache will not store a response if it is too big and the app will always perform the request despite the HTTP header directive.

URLCache can store data both in memory and on disk. The documentation in NSURLCache.h says that the default sizes are:

  • 4 megabytes in memory
  • 20 megabytes on disk

My advice is to inspect the cache size at runtime because you can find different values from the documented ones.

Whilst the algorithm used to decide when something is too big to be cached is not public,  I spent some time trying to determine the maximum size for a response to be cached. According to my calculations, the response size must be no bigger than ~5% of the size of the on-disk cache.

It’s important to measure the network response size as uncompressed payload. It can make a big difference since most of the network calls nowadays use JSON which is text based format and usually has high entropy.

If the default cache size is not enough for your app, you can increase it in one simple line of code:

URLCache.shared = URLCache(memoryCapacity: 6*1024*1024, 
                             diskCapacity: 40*1024*1024, 
                                 diskPath: nil)

Remember that the sizes are measured in bytes. So in this example the cache is set to:

  • 6 megabytes in memory
  • 40 megabytes on disk

My advice is to set it as soon as the app starts before any network calls are fired.

This small change allowed us to save up to ~10% of the iOS traffic on one of our busiest endpoints.

I hope this little hint can speed up your apps, save some battery on users’ devices, and decrease the load on your backends too!