DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • MCP Is Coming to Your Desktop Applications
  • Building High-Performance Time-Series Applications With Java and QuestDB
  • Building Time-Series Applications With Java and InfluxDB
  • Small Language Models on Apple Silicon for Responsive AI Applications

Trending

  • Member Spotlight: Shai Almong
  • How an AI Software Factory Works: From Developer Intent to Production
  • How Kestra Unifies Enterprise Workflow Orchestration and Agentic AI
  • Introducing senro: A Pipeline Engine You Program in Go

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Designing Frontend Applications for Failure, Not Just Success

Designing Frontend Applications for Failure, Not Just Success

Design frontend apps for real-world failures like slow networks, failed APIs, expired sessions, and duplicate actions, not just smooth demo flows.

By 
Somya Biswari
·
Oct. 28, 26 · Opinion
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
3 Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

Most frontend applications were built with the success path in mind. A user will typically open a webpage, load their data, complete a form, submit it, and receive a response or confirmation to allow them to continue on their way. That's the typical scenario you'll see in demos, design reviews, and when walking through your application with a customer.

However, real customers don't follow the happy path.

Their internet speeds might be slow. An API could return a 500 error. The session could time out while completing a checkout process. A user can accidentally double-click a button. A form submission might fail partially. A required third-party service could be down. The browser could refresh at exactly the wrong moment.

Therefore, in production, failure is not something that happens by accident; it's simply part of how most people interact with your web application.

This is why frontend applications should be designed not only for success, but also for failure.

The Happy Path Is Not Enough

The happy path in the development process is key to developing an optimal user journey. This will help a team develop the product flow as well as design the base of their experience. If your application only functions properly under the best possible conditions, then you have not developed a production-ready application.

If your frontend application is designed with the assumption of successful actions by the user, it could be very frustrating for them. For example, the loading indicator on a page could run indefinitely. The submit button could accept multiple click events from the same action. 

When an error message was generated in the application, it could simply state something like "An error has occurred" without providing any guidance to the user about how to proceed. Finally, when there were problems accessing APIs associated with content displayed on pages, users may see a blank page with no indication as to why they are seeing this. In addition to being frustrating for users, losing all inputted information due to a page refresh or timed-out session is also a reliability problem.

An effective frontend application should provide answers to at least two questions: 

  • What does the application look like while working properly? 
  • And what happens if things do not work correctly?

Loading States Should Be Intentional

Loading states are often overlooked as small details, but they set the reliability of the user's first impression. A generic loader for a short wait might be sufficient, but it isn't going to cut it for all situations.

Skeleton loading is useful on pages with structured content to give the interface a sense of stability. On forms, the submit button needs to clearly indicate that processing is taking place. For long-running tasks, users will want either a progress message or some indication that the system is still processing their request.

Ultimately, your goal when designing a loading state is to avoid ambiguity. The user shouldn't have to wonder if the app is frozen, still loading, or simply broken.

A good loading state communicates that the system has received the action and is working on it.

Error States Need Recovery Paths

Most applications have some type of error message, yet fewer than most offer paths for users to recover from these errors. When an application gives you an error such as "Failed to Load Data," then that is factually accurate; however, this information is not helpful to the user at all.

Good error processing will tell the user what occurred, what actions they need to take next, and whether their previous efforts are saved. An example would be if a payment process failed prior to charging your card; in this case, the application could inform the user that they should try again. In cases where the application cannot determine whether the payment was successful, the user should not be prompted to resubmit. Instead, the application should suggest that the user either wait and see, attempt to refresh and try again, or reach out to support.

Error states should ideally be unique when possible. Validation errors, permission errors, network timeouts, server-side errors, and expired sessions are examples of types of potential errors, each of which may require a completely different way of recovering from.

The goal is not just to display an error. The goal is to help the user continue safely.

Forms Should Protect User Input

User frustration often stems from failures at the frontend level. A user may have spent many minutes entering data into a form that will now be lost when their session expires or fails on an API call.

The best way for forms to recover from user errors and maintain usability is by preserving user-entered input. There are several methods to achieve this, including use of local state, draft saving, autosaving, and backing up form entries in the backend with partial submissions. Most users would appreciate minor improvements to usability, even if simply retaining field values during failed submits.

Additionally, forms should prevent multiple submissions. Disabling a form's submit button once the first time it has been clicked is a good practice; however, disabling a form's submit button does not ensure against duplicate submissions being made to the backend. The backend method for handling duplicate requests must be safe. Safe handling of duplicate requests can be achieved through backend processes, including idempotent key patterns.

Partial Failure Should Not Break the Whole Page

When web pages have many dependent APIs for different things (e.g., profile info, suggestions, bill, etc.), if one of those APIs fails, it does not necessarily mean that the whole page has to be unavailable.

It would make sense to create some type of partial failure state so that although the whole page cannot operate as intended, you could still use other parts of the page while a second part of the page provides an option to retry.

A dashboard may provide a list of available areas but mark sections that are unable to load. And though you may be able to see basic data about a product, in the event that its reviews or suggestions fail, you will still be able to review it.

Ultimately, this method allows your users to feel like they have access to more than just what is currently working.

Expired Sessions Should Be Handled Gracefully

A typical problem with how many programs manage session timeouts is that they abruptly send users to a login screen when the user's session has timed out. It is possible for an application to be designed so that if the user's session times out while using the application, after asking the user to log back in, it will direct the user back to where they were in the process as opposed to being sent back to the beginning of the process. The loss of information on forms makes this particularly important.

In general, from the user's perspective, timing out of the user's session should be seen as just a minor disruption rather than a full stop.

Observability Matters on the Frontend

Designing for failure is not only about UI states. Teams also need visibility into how failures happen in production.

Teams can monitor these factors as well as other user behaviors to determine where users are experiencing problems in order to develop design solutions to address them.

Tracking failed API calls, JavaScript errors, slow load times, rage clicking, repeated retry attempts, form abandonment, and unusual navigation patterns through frontend applications will give teams insight into where users are experiencing problems.

While backend services may be running smoothly and providing a healthy status, it doesn't necessarily mean that users have a good experience with your product. Frontends are typically where issues in production are most visible.

Conclusion

Frontend apps typically get judged on how visually appealing they appear while running smoothly. The true measure of a frontend app's production quality is when it actually breaks.

It is important to note that designing for failure does not make an application less positive or overly defensive; instead, it creates a sense of trustworthiness with the end-user. When designing for failure, the application demonstrates respect for the user's time and effort. Additionally, the design of an application to fail properly protects the user from unintended consequences due to its preparation for a variety of real-world operating conditions.

The happy path may help you demonstrate your application to potential clients, but successful design for failure builds trust with your users.

applications

Opinions expressed by DZone contributors are their own.

Related

  • MCP Is Coming to Your Desktop Applications
  • Building High-Performance Time-Series Applications With Java and QuestDB
  • Building Time-Series Applications With Java and InfluxDB
  • Small Language Models on Apple Silicon for Responsive AI Applications

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook