Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 13 min read

The Experience We Forgot to Build

Rethinking User Experience from Product Design to Software Development Introduction: When a Feature Works but the Experience Doesn't A while ago, I completed my identity verification, often called KYC (know y

Rethinking User Experience from Product Design to Software Development

Introduction: When a Feature Works but the Experience Doesn't

A while ago, I completed my identity verification, often called KYC (know your customer), on an investment platform. I filled in the required information, submitted my documents, and received a message indicating that my submission was successful. That should have been reassuring, but I soon realized I had no clear way to know what happened next.

Was my verification still being reviewed? Had it been approved? Was there an issue with one of the documents? Did I need to do anything else? I could not tell from the application, so I contacted customer support. More than once.

I ran into a similar problem when I raised a support ticket. The application let me describe my issue and submit it, but I could not find a useful way to revisit the ticket, check its progress, or see whether someone was working on it. I eventually sent an email and explained the same problem again.

What bothered me was not simply how the application looked. It was that two important processes seemed to stop at the point where I had done my part. I could submit information, but I could not reasonably follow what happened afterward.

Another experience made the problem feel more serious. I deposited some money to test an investment product. When I tried to invest it, the amount was deducted from my wallet, but it did not appear in my investment balance. For more than 24 hours, I could not tell where the money was or what had happened to the transaction.

Was the investment still processing? Had it failed? Would the money be returned? A delay might have been understandable if the platform had explained what to expect, shown a meaningful transaction status, or provided a reliable way to follow up. It did none of these.

The uncertainty changed my willingness to use the product. I began wondering whether I could trust the platform with a much larger investment and whether I would be able to access my money when I needed it. That experience did not prove that the platform was financially unsafe. It showed me how an unclear experience could make a product feel unsafe.

It also made me think about how we define a completed feature. If a user can click Submit and the backend successfully stores the request, have we solved the user's problem? Or have we only completed one step in a much larger journey?

What Does It Actually Mean to Solve a User's Problem?

As developers, we often work with requirements that are broken down into individual tasks. Build a form. Connect it to an endpoint. Validate the fields. Show a success message. Test the happy path. Mark the ticket as done.

There is nothing wrong with breaking work into smaller pieces. It is how we make complex projects manageable. The problem begins when we confuse the completion of those pieces with the completion of the user's goal.

Take a customer support feature. A requirement might say, "Allow users to submit support tickets." The team delivers a form, stores the ticket, and returns a reference number. Technically, the feature works. But why did the user raise the ticket in the first place? They wanted help with a problem. Submission is only the beginning of that process. The user may need to find the ticket again, see whether it has been acknowledged, provide more information, and understand the final response.

This is the distinction I want us to pay attention to: technical completion tells us whether the software performed an operation. User completion asks whether the person achieved a meaningful outcome, or at least received a clear and usable result. Both matter, and neither should be mistaken for the other.

User Experience Is More Than What Users See

When people talk about user experience, the conversation sometimes moves quickly to colours, spacing, typography, and whether an interface looks modern. These things matter. But an attractive screen cannot compensate for a missing process. A beautiful KYC form does not tell me what happened to my verification three days later.

It is also possible to have the necessary functionality and still provide a frustrating experience. A platform might technically expose a verification status, but bury it in an unexpected menu, label it with internal terminology, or show a message that leaves the user unsure what to do.

This is why I would not treat interface design and user experience as competing ideas. The interface is one part of the experience. The rest includes the steps people must take, the information available to them, the reliability of the system, and the effort required to accomplish their goals. The human-centred design standard ISO 9241-210 takes the same broad view, treating user experience as a person's perceptions and responses before, during, and after use, not just their reaction to a screen. The useful question is not only, "Does this screen look good?" It is also, "Does this product help the user move forward?"

Software Is Also a Form of Communication

When a user takes an action, the application responds: a spinner, a notification, a changed button, a new screen. But saying something is not the same as being understood. Does that response actually tell the user what they need to know?

Consider the message "Submitted successfully." What was submitted? Is it being processed? Is there an estimated review period? Will the user be notified? Can they return to see the outcome? A success message can be accurate while still leaving important questions unanswered. Compare it with an alternative (the timing is only an example):

Before After
Submitted successfully. We've received your documents. Most verifications are reviewed within two business days. We'll email you when there's an update, and you can check progress at any time under Profile > Verification.

The second message answers what happened, what happens next, how long it should take, and where to look. It also makes promises the system must keep: a review time the operations team can actually meet, a notification that is really sent, and a status page that exists. A message is only as honest as the product behind it.

The principle of visibility of system status, described in Jakob Nielsen's usability heuristics, is relevant here. Systems should keep users informed through appropriate feedback. The important word is appropriate. Saving a theme preference may only need a brief confirmation. Verifying an identity or processing a payment may require much more.

Good communication also includes failure. "Something went wrong" rarely tells me whether I should retry, wait, check my account, or contact support. When possible, an application should explain what it knows, avoid claiming certainty it does not have, and give the user a reasonable next step.

This matters most when money is involved. Seeing funds leave one balance without appearing in another is not just a missing success message. The user needs to know whether the transaction is pending, completed, reversed, or requires attention. If the platform does not know the final outcome yet, it should communicate that uncertainty rather than present a misleading result.

The same applies to support tickets. Being told a ticket was submitted is different from knowing whether it was received, assigned, investigated, or resolved. Without that visibility, I found myself calling and emailing customer care about an issue I had already reported in the app. The burden of tracking the process had shifted to me.

Designing Complete User Journeys

A common way to miss important parts of an experience is to design and review screens in isolation. We look at the onboarding screen, the upload screen, and the confirmation screen. Each one may appear complete. But what happens between them, and what happens when the user returns tomorrow? The UK Government Digital Service puts this well in its Service Standard: solve a whole problem for users, not just the part your team happens to own.

For KYC, the journey might include submitting documents, waiting for review, receiving an outcome, correcting rejected information, and eventually accessing the service. If we design only the submission screen, we have not designed the verification experience. We have designed an entry point into it.

A useful exercise is to map the journey from the user's perspective. What does the person know at each stage? What are they waiting for? What happens if they leave the application and come back? What happens if a request fails halfway through? The answers should influence both the interface and the underlying system. A status screen is not useful if the backend does not maintain reliable statuses. A "Try again" button is not useful if repeating the request could create duplicate records. An email update is not enough if it points the user to a process they cannot complete.

This does not mean every action needs a tracking dashboard. The level of care should match the stakes, duration, frequency, and cost of uncertainty. A quick, reversible, low-risk action may need only a confirmation. A process that affects someone's identity, their access to a service, or their money deserves more deliberate treatment. The objective is not to add complexity everywhere. It is to avoid leaving important journeys without visibility or closure.

Engineering the Experience, Not Just the Interface

This is where I believe engineers have a particularly important role to play. We are often the people who see how the intended user journey connects to the behaviour of the actual system. That gives us an opportunity to identify gaps before users encounter them.

Suppose a designer provides a KYC status screen with labels such as Pending, Approved, and Rejected. The frontend needs an API that exposes the current state. The backend needs a reliable source of truth for that state. The product team needs to define what each state means, and what the user can do when verification is rejected. Without those decisions, the screen is only a representation of an experience the product may not actually support.

Loading, empty, and pending states are not interchangeable either. A loading state means we are waiting for information. An empty state means we have no relevant records to show. A pending state means the request was received but the process is still underway. If we treat all three as a generic spinner or a blank screen, we make the system harder to understand.

Payments make the engineering implications clearest. Imagine a user initiates a payment, the server processes it, but the network connection drops before the application receives the response. If the frontend simply displays "Payment failed" and invites a retry, the experience could be misleading and even charge the user twice. The same applies when money moves between internal balances, as it did in my case: a transaction may pass through several states before it settles. The system may need transaction references, idempotent operations (designed so that repeating the same request cannot apply it twice), status reconciliation, an accurate status history, and a clear escalation route.

The frontend cannot solve that problem through wording alone, and the backend cannot solve the user's uncertainty through reliable processing alone. A reassuring interface cannot compensate for an unreliable ledger. Good experience depends on accurate underlying behaviour and honest communication about it. That includes accessibility: if a status changes, someone using a screen reader should be told. W3C's accessibility guidance on status messages exists precisely so that updates like these reach assistive technology without the user having to hunt for them.

None of this means engineers should independently redesign every requirement. It means we should ask questions when the implementation reveals a gap. What happens after this request? Can users recover if it fails? How do we know the state on screen is still accurate? Those questions are part of engineering a usable product, not distractions from engineering work.

Building Good Experiences Is a Shared Responsibility

It would be easy to read these examples and blame the designer for missing screens or the developer for poor feedback. In practice, incomplete experiences rarely come from one person or one discipline. Product, design, frontend, backend, QA, and support each see a different part of the journey. A backend engineer may point out that a proposed status cannot be determined reliably, and a support agent may be the first to notice that users keep asking a question the application never answers.

The problem comes when each team optimizes only for its own handoff. A design can be approved, an endpoint can pass its tests, and a frontend task can be marked complete while the end-to-end experience remains confusing. A better review asks everyone to walk through the process as a user would, including delays, errors, and returning users, and to ask whether the person has enough information and control at each meaningful point.

The Experience Doesn't End When We Deploy

Even a carefully planned journey will not behave exactly as expected in real life. People use software in ways we do not anticipate, and external services fail. Deployment should be treated as the beginning of another kind of learning, not the end of responsibility for the experience. We can look at where users abandon a process, how often they retry, and how often they contact support after using a feature.

Metrics need interpretation. A high ticket-submission rate does not necessarily mean the ticketing feature is successful. It could mean users have more unresolved problems. A low support-contact rate could indicate a clear product, or it could mean users cannot find a way to ask for help. Numbers become useful when we connect them to the problem we are trying to understand.

The Business Cost of Uncertainty

When users repeatedly need to email or call about tickets they have already raised, support teams spend time answering avoidable status questions and dealing with duplicated reports. Not every support request is evidence of product failure, but patterns of repeated contact can reveal missing visibility or incomplete journeys.

Poor experiences can also weaken trust. In my case, the uncertainty did not simply make one transaction frustrating. It made me hesitant to invest more money. I did not close my account; I just became more cautious with it. That kind of quiet withdrawal is easy to miss, because a user may remain registered while becoming less active, reducing transaction volume, or eventually moving to another service. Growth is not only about convincing someone to sign up. It also depends on giving them enough confidence to return, transact again, and recommend the product to someone else.

Teams can look for signals such as repeated contacts per issue, unresolved ticket age, transaction-status enquiries, and retention among users who encountered delays. These measures do not establish causation on their own, but they help teams ask whether an experience is earning or losing confidence over time.

Six Questions Before We Call It Done

Before calling a feature complete, I think a team should ask:

  1. What is the user trying to achieve?
  2. What happens after the main action?
  3. Can the user understand the current state?
  4. What happens when something goes wrong?
  5. Does the user know what to do next?
  6. How will we know whether the experience actually works?

These questions are not a substitute for research or testing. They are a practical way to expose assumptions that may otherwise survive all the way into production.

Conclusion: Did We Actually Solve the Problem?

In the end, the money did arrive, a couple of days later. But getting there meant following up with customer care several times. Each time I spoke to a different agent, and because there was no way to track the issue, I had to narrate the whole problem from the beginning again. The platform had accepted everything I gave it. What it never did was tell me what happened next, and that silence is what cost it my trust.

We can build technically functional software and still leave users doing unnecessary work. Sometimes the solution is clearer communication. Sometimes it is a better-designed journey. And sometimes it requires engineering decisions that were never included in the original requirements.

The next time we review a feature and say it is done, perhaps we should ask one more question: did we finish implementing what was requested, or did we actually help the user accomplish what they came to do?

References and Further Reading

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.