://shaun.church

Optimistic User Interfaces: A good kind of lie

1 July 2020

What happens when you click a button on a web page?

Like the Twitter or Facebook like buttons, perhaps it changes to let you know the interaction did something.

In some cases it might show a Loading... state while it communicates with a server to find out if your action was successful, like this:

.

Or maybe it doesn't, like this:

.

This second example demonstrates what we're talking about when we say the interface is optimistic.

So what's going on here, and why?

Well I'm glad you asked...

Predicting the future

Let's think about what happens when you click the like button on twitter:


  1. A click event fires on the button, or a form submission occurs.

  2. An API call is made with a request to mark this postId: 323423 as liked by this user: @shaunchurch in a database somewhere.

  3. The server responds HTTP 200 OK after some period of time.

How often is there an error?

Assuming your API is reliable, we can predict with some confidence that simple, regular actions will succeed most of the time, and for most users that try it.

Please wait...


The Loading... state is an unpleasant experience. What's worse is that how long it takes depends on a variety of factors out of our control: the speed of the user's internet connection, the distance the user is from the server, the competing traffic on those internet routes, and finally our own server response time.

Loading spinners make the app feel slow and cumbersome. It quickly gets frustrating.

Since we believe the chances of a request being successful are high, we have another option: assume this one will be too, and update the UI immediately to reflect the final state after a successful action.

Here's that optimistic button again:

.

Making mistakes

That sounds great, and when things follow the happy path the user will experience a snappier app.

But what happens if there is a problem? 😲🚨

What if the user loses signal, or there's an error on a relay server, or a million other things that have a small but non-zero chance of happening?

It goes like this:

  1. Catch the error.
  2. Revert the change back to the state of the component before the request was made.
  3. Optionally, show an error message to the user, so they know the action failed afer all.

This is not a great experience. However, if the error rate is low, it may be a worthwhile trade-off for the advantage of all the successful interactions being significantly better. This needs to be judged based on the performance of your own systems, and the importance of each interaction and how it's communicated.

It's possible that the user would fail to see an error notification, and assume an action that appeared successful actually was not. It might be wise to avoid using this technique for mission critical actions.

The technique really shines for simple, frequent interactions such as liking a tweet. It may or may not be appropriate in more sensitive contexts, like sending payments from a bank account.

Conclusion

Optimistic UI update patterns give us the opportunity to make our apps feel more responsive to user interactions. They allow us to reduce visual complexity with loading states, but increase the burden of communicating errors to the user, and perhaps also the chance of losing data the user thought was saved.

It should be used carefully, but can be applied in many contexts to get a noticeable boost in perceived performance and user satisfaction.

Give it a try!

If you made it this far, why not follow me on twitter.