· Tim van der Weijde · Microservices · 5 min read
Eventual Consistency & an user interface
“Fake it, until you make it”
Introduction
If you live in a world of systems designed with a Microservices or CQRS architecture, you probably have heard of the term “Eventual Consistency.” It is related to the delay between an asynchronous action and the state of the system.
For example, when a user updates an address in a web app, an action/command is first asynchronously sent to a server to update the address. The action/command will then be processed asynchronously over time. There will be a delay before the database is actually updated.
So you think, what is the problem?
The problem or challenge is the asynchronous behavior, the delay, and the fast response of your user’s UI.
In the example above, we have a web app that is blazing fast. 😉 After sending the command to the server asynchronously, the web app’s job is done and it will return a response to the user.
The command will be picked up eventually(!) and after processing, the address is updated. The database becomes consistent(!) again.
However, before the command is processed, the web app already returns the address page to the user. This address page shows the old address in the database (stale), as the command has not yet been processed.
The user will certainly be confused. (Remember, most users live in a digital world where everything seems consistent all the time.)
What is Eventual Consistency in plain English to a business user?
Before I show you a few options for handling the user experience, let me share an analogous example you can use to explain it to a business user. In the non-digital world, many cases are naturally eventually consistent.
(I love analogous (fictional) examples; if you have another one, please leave a comment below.)
Give your business user a pen and paper. Tell them they are responsible for creating new users in a paper system by getting requests and generating unique customer IDs.
Then you start giving requests with user names. After each request, you immediately ask for the customer ID. The business user won’t be able to keep up with providing the correct customer IDs right away. Eventually(!), the user generates the IDs and can provide them to you. You both now have the same customer IDs and are consistent(!) with each other.
A few ways to handle the user interface (UI)
As a developer, you have several options for handling the user interface. Each option impacts the user experience and also your development time.
Option 1 – Do nothing, render the UI as normal with old data.
This option takes no extra development time; however, the user experience is terrible, to say the least. You’ll need to explain eventual consistency to the user and have them handle it themselves. I wouldn’t recommend it.
Option 2 – Put in a delay of the response to the user (give the server process more time).
Adding a delay will hurt the user experience, as no one likes to wait for a webpage to load.
Most of the time, the user gets the new, consistent data and will take the right actions if needed. But, “most of the time” isn’t “all the time.” If the server is very busy, the user may still see old data.
Option 3 – Use a confirmation screen (another way to delay).
Adding a confirmation screen can improve the user experience if there aren’t too many actions. (Otherwise, you’d have a lot of pop-ups.)
The action/command is sent before showing the confirmation screen. It takes time for the user to dismiss the confirmation screen, giving the server more time to process.
The user experience will improve, but the delay will only help most of the time—not all the time.
Option 4 – Fake it until you make it.
This option has a few variations, depending on the priority of user experience and your development time.
First, when the user performs an action, you “know” what’s going to be processed on the server, allowing you to make a reasonable guess about what the UI’s state will be.
You need to maintain this state on the UI side and keep it comparable with the server state.
To the user, you show the UI state, which will eventually be consistent with the server state.
For example, you can show a message indicating the current data is “old” data with a timestamp. You let the user decide when to refresh the data/page. While refreshing, compare the UI state with the server state; if the server state is up-to-date, you can display the results to the user without the message.
Another way to refresh the data is by using a polling technique. Instead of asking the user to refresh the page, you check in the background if the server data is up-to-date, and then refresh the page or only the required data on the screen.
A final way is to use a publisher/subscriber technique (e.g., with SignalR). On the UI side, you can subscribe to events from the server. When the user’s action is processed on the server, the server publishes an event. This event contains the up-to-date data on the server, which will be handled on the UI side.
Final thoughts
There are many ways to handle eventual consistency. Sometimes, you don’t need to handle the UI at all, which simplifies things. But most of the time, users are involved, and they expect a good or great user experience. User experience is everywhere (e.g., websites, phones, etc.), so it’s important to reflect on it.
Please leave a comment below if you like this or have any questions. Thank you!