Network timeout, retries are normal user behaviours when building a digital product

If you have ever used or built a digital product especially when an activity leads to an OUTCOME such as:

A user completes a registration form and then HAS AN ACCOUNT
A user clicks “Book Ride” and then HAS A DRIVER ASSIGNED
A user clicks “Send Message” and then HAS A MESSAGE DELIVERED
A user clicks “Place Order” and then HAS AN ORDER CREATED
A user enters their card details, clicks on “Make Payment” and then RECEIVES DEBIT ALERT”

In all these cases, if the user does not immediately see the associated outcome, they tend to try again, refresh, click twice, open another tab, call someone (and whatever they can to make sure things work). Oh, before you start to blame the users or categorize them as “not tech-savvy” in your mind, please note that this is not a bad behavior – we all don’t trust unstable systems, do you?

The expectation is that no matter how many times the action is triggered (either because of network issues or user behavior), the outcome should happen once and only once. Your system should be designed for that reality – This is called idempotency.

As a system architect or developer, always have the mindset that any operation that: creates, updates, triggers or transitions state must assume that users might execute more than once.

With that mindset in place, when implementing functionalities in that categories of operations especially for critical systems like Fintech, here is the strategy I often advise engineering teams to adopt:

  • Attach a unique request ID (idempotency key)
  • Store the first result
  • Return the same result for retries

In API design, this is often passed as headers, when the client sends a request with a specific idempotency key, the server checks if that key has been used before. If it has, the server returns the same response as the original request, ensuring that repeated requests don’t result in duplicate actions.

An engineer developing a wallet payment system once asked me:

Abiola, what if I just put a database constraint so a transaction can only happen once? Do I still need idempotency keys?

It’s a fair question but while database constraints help, they are not enough on their own.

I broke it down using a simple flow described below:

A user clicks “Debit Wallet” and then HAS A SUCCESSFUL DEBIT

Now imagine typical conditions like network delay and they retry

With only a database constraint:

  • The first request hits the database, transaction is processed
  • The second request also goes through your entire application logic, reaches the database and then fail due to the constraint

The result is that there are no duplicate debit but you still end up consuming compute resources because you would open a database transaction, creating load on your system. Consequently, your application logic would need to handle and interpret the database error.

Obviously, this becomes expensive and noisy at scale!

Compared to implementation of idempotency at application level

  • The first request is processed normally, result is stored with the idempotency key
  • The second request is intercepted early without the need to reach the core business logic or make a database write and the outcome is the exact same response is returned immediately

This offers a faster and cleaner system behavior

So which should you use? Use both.

Use idempotency keys for performance, user experience, and system efficiency (see it as a proactive control that prevents duplication early)

Use database constraints as a safety net for data integrity (see it as a reactive protection that stops duplication late) – not forgeting that the queries should be within a BEGIN … COMMIT for database lock.

So, next time you are building an application, ask yourself: “can my system survive retries?“

On a final note, when you are building applications in an environment where your users are rightfully skeptical or have infrastructure challenge, idempotency is not just a “best practice” it is survival engineering.

Thank you for reading.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *