Tag Archives: Concept

Versioning with Local Storage

Local Storage is a HTML5 feature, which comes with most modern browsers. It is a great tool to store client side data. Getting and setting data is very fast and with a good concept, you could save some HTTP requests or run the application offline. Though you should keep in mind that using Local Storage depends on a good data management which keeps the data consistent and prevents from memory exceeding. If you are new into Local Storage, you should notice Mozillas DOM Storage guide before continuing to read.

The first thing you should remember is that Local Storage underlies the same origin policy (SOP). The local data will be stored just for the current domain. This security policy prevents from third party access and helps to not get in conflict with other data. As you already know, the data will be stored as key-value-pairs. So let’s have a look on how the example data could look like.

Imagine we create a very simple mail client, which pre-fills the form and buffers all outgoing mails if the user goes offline. Local Storage is good to deal with offline apps.

Eventually we are going to decide to change the API interface to v2, which is not compatible with v1 anymore. In this case we have to change the api_endpoint setting.

 

The problem

But what would happen if API v2 would not be stable enough? What if our backend throws critical exceptions? In this case we have to roll back to version 1. But some of our customer app-clients are still updated to use the unstable version 2. In this case we just have one option: Fixing the issue in production.

Hence we should use version-controlled data.

To solve the problem, we have to link the data-key with the correct version; so only exclusive keys which make sense to be version-controlled. The buffered_emails property will be shared over all versions. So we’ll keep it global. Okay, let’s start at version 1.

Don’t wonder about the version syntax. 100 means 1.0.0. I’ll explain the reason later.

That’s the key! We just have to integrate the version within the data-key. We could roll out as many client versions as we want to. Just the number of version would be increased. Switching a version becomes very easy.

How to handle different versions?

First of all, we have to add a version prefix to the data-keys, who identifies each entry. The current version must be deployed in addition to map the correct key.

The JSON below is just a concept for how the version-control can be managed.

The _versions key is prefixed with an underscore, to prevent key-conflicts. But it’s just a concept. You can name the property as you want.

Each version must be defined within _versions and must contain all mapped keys. This is quite important because it is impossible to iterate over all Local Storage entries. This guarantees to identify all related keys.

The buffered_emails property remains still “global”.

Limitations

Now we have a great way to manage each version within our client-side app. However Local Storage comes with another limitation: limited disk space.

The W3C recommends a five megabyte storage and the most browsers follow them.

A good way to reduce unneeded data is to drop old versions from your Local Storage. As you remember, we just keep version controlled data to support the option of software-roll-backs. Though our software should be well tested and stable enough to prevent these issues. Hence it should suffice to keep about three versions stored.

Dropping deprecated versions

The simple script below describes how versions can be dropped. The last three versions are still kept.

As you remember we stored the version 1.0.0 as 100 and 2.0.0 as 200. The reason is because we can cast the version to an integer and sort it. This makes dropping old data easier. You can add any numeric version you want:

Major.Minor.Bugfix / 5.15.63 would take 51563.

You should delete deprecated versions before releasing a new one.

Quota Exceeded Error

Even dropping old versions to save disk space can not always prevent memory-exceeding. In case of exceeding quota the browser will throw a QUOTA_EXCEEDED_ERR exception.

It is very hard to identify which key or version caused the error. In case of this error, I would recommend to delete all data.

Removing all data is the safest way to fix the issue. However you should try to avoid this bug due to limiting versions and data. ~5MB are not much of data but definitely enough for your app-client.

Additional notes

There are some things you should be aware of.

Local Storage can only persist values with type of string. If you try to store any other type, your browser will cast the value to string and stores them anyway. Storing an object results in “[object Object]”. If you have to store complex data, it’s highly recommended to use JSON.

If you will get the QUOTA_EXCEEDED_ERR over and over, you have to deal with detailed data-analyzation instead of clearing the storage.

If you have to support old browsers like IE7, using Local Storage is a non option and can be a pain in the ass. Please have a look at the related caniuse.com article. The common fall back is based on cookies.

Conclusion

This article is just a concept for managing client-side data with Local Storage. The scripts and data schemas are examples.