You click Save, the server records your changes, but the response never reaches your browser. The screen can’t confirm the save. Clicking Save again seems reasonable, but that’s awkward if it creates a second copy of what you just saved.

In reliability work I did for an existing community application, recovery had to account for that gap. The application maintains event and participation records. A missing response could mean that nothing was saved, or that everything was saved and the browser never found out. A simple “Save failed. Try again.” would claim more than the browser knew.

For example, suppose you’re adding an event, the database commits it, but the response is lost. If the next click sends a new request to create an event, the server may oblige. Disabling the button while a request is running could help with repeated clicks, but it wouldn’t tell the browser what happened to the first request.

The implementation gives each save attempt a request identifier associated with the signed-in account. The server stores the changes, their audit entries, and a receipt for the completed command in one database transaction. (Saving the receipt afterward would have left another gap: the changes could be committed without the evidence needed to recognize a retry.)

The browser keeps the original request as long as its outcome is uncertain. Retrying sends that same request under the same account. If the attempt already committed (that is, the server already has a receipt record), the server returns its receipt. If it didn’t, the server can process the request, with the usual checks. Reusing an identifier with different contents is rejected, and version checks prevent stale edits from silently overwriting newer changes. “Try again” has to mean something more precise than “send whatever is in the form now.”

The interface has responsibilities here too. It needs to both explain that the outcome is unknown and also keep the pending request intact. If your session has expired, it needs to let you sign in again. A different account must not see (or retry) your pending request, and signing back in as the original account shouldn’t submit it automatically. You still have to select Retry.

In staging, tests deliberately lost the responses after two synthetic saves had committed. Both editors retained their pending requests. Signing back in under the original account and explicitly retrying returned the existing receipts. The command count increased by two for the intended saves and stayed there through recovery; checks of the saved records and receipts confirmed that the retries hadn’t made additional changes. A reassuring message on the screen wouldn’t have been enough evidence.

The recovery release was deployed, but those failure cases were tested in staging. The release checks didn’t exercise authenticated production editing. They demonstrate the tested recovery behavior, not a guarantee against every possible duplicate or interruption.

There is a browser limitation too: this implementation keeps the pending request in session storage, which supports navigation and reload in the same tab, but it doesn’t guarantee recovery after closing the tab or clearing browser storage. “Close it and try again” might discard the information needed to work out what happened. If that information is lost, the server’s result would need to be checked manually before creating a replacement request.

When testing a Save button, include the case where the save succeeds and the confirmation doesn’t arrive. The user still needs an answer, and another Save button isn’t necessarily it.

—jhunterj

Join the conversation

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