← Back to list

How Long People Will Actually Stare at a Spinner Before They Quietly Leave

Part four of a series on building software people don’t quietly hate. Last time: the four kinds of loaders and which one to pick. Today: a…

FLACKO in Tech and Me, Loving It or Hating It · 2026-06-05 11:17 · 50 claps · 7.6 min read paywalled
#vibe-coding #ux-design #user-patience #ux-psychology #loading-state
Open on Medium ↗
Wiki topics: UX · UI/UX Design PSY · Psychology 💻 · Programming 🔧 · Data Engineering

How Long People Will Actually Stare at a Spinner Before They Quietly Leave

Part four of a series on building software people don’t quietly hate. Last time: the four kinds of loaders and which one to pick. Today: a stopwatch, your users, and the surprisingly specific psychology of how long a spinner can carry the weight before it starts working against you.

Every spinner has a shelf life. Past it, you’re not loading — you’re stalling.

Every spinner has a shelf life. Past it, you’re not loading — you’re stalling.

In part three, I laid out the four kinds of loaders skeletons for whole pages, progress bars for measurable waits, inline spinners for the small “got it” moments, and optimistic UI for the times when no loader at all is the right call. I told you each one tells the user a different story.

Today I want to put a stopwatch on one of them.

The inline spinner, that little circle going round and round inside a button or beside an action, is the most quietly powerful element in your app. It’s also the most psychologically fragile. The exact same spinner, with the exact same animation, at the exact same speed, can feel trustworthy at one second and broken at six. The thing that changes isn’t the spinner. It’s the user’s patience curve, and that curve has some surprisingly precise breakpoints.

Once you know where they are, you stop building apps that “just feel slow” and start building apps that feel responsive at the same actual speed. Let’s walk through it.

The first second is its own world

Here’s the rule almost nobody knows, and the one I see violated constantly: if something will take less than one second, do not show a spinner at all.

This sounds backwards. Surely some feedback is better than no feedback, right? No. Under one second, a spinner becomes its own problem. It flashes onto the screen, the animation barely starts, and then it disappears, and your user’s brain registers a tiny something just happened that I don’t understand. The screen flickered. There was a thing, and then there wasn’t. Your app didn’t feel responsive; it felt twitchy.

The weird truth is that a fast action with no spinner feels faster than a fast action with a spinner that barely had time to draw itself. Just show the result. Let the user assume the app was instant, because effectively it was. Spinners are for waits long enough that your user would otherwise wonder if something broke. Under a second, nobody wonders. They see the new state and move on.

The lesson: a spinner you barely see is worse than no spinner at all.

Under a second, no loader at all. The flicker of a spinner you barely see does more harm than the silence it was trying to fill.

Under a second, no loader at all. The flicker of a spinner you barely see does more harm than the silence it was trying to fill.

Seconds two through five — the spinner’s home turf

Between roughly one and five seconds, a plain inline spinner is doing exactly what it’s designed to do.

This is the spinner’s natural habitat. You clicked something, the app needs a moment, and the little circle’s job is one thing: acknowledge that the system heard you and is working on it. No text needed. No clever animation needed. Just movement, in a small area, while the system does the thing.

People will wait through these few seconds without thinking about it at all, as long as the spinner is present. Remove it, and they start to wonder if the click registered. Add too much around it, and you accidentally signal that this is taking longer than it actually is. A bare spinner is enough.

This is also where most clicks in any well-built app live. Submit a form. Save a setting. Send a message. Most of these resolve in two or three seconds, and a plain spinner is doing all the emotional work quietly, invisibly, exactly the way good UX should.

The rule here is almost embarrassingly simple: between one and five seconds, a plain spinner is enough. Don’t overbuild it.

Past five seconds, the spinner starts to lie

Here’s where it gets interesting.

After about five seconds, a plain spinner, one that’s just looping in silence, starts to feel broken. It hasn’t changed. It’s been spinning that long. The user has no way to tell whether anything is actually happening anymore, or whether the system has frozen and the spinner is just animating because it’s coded to animate. Patience drops sharply. People start hovering near the back button.

The fix is small but psychologically enormous: add a tiny piece of text. Just a word or two. Loading… Saving your changes… Almost there… That static text buys you maybe one more second of patience. It’s not magic, but it’s something the user feels slightly more informed, which buys you a little more time.

The bigger move, though, is text that changes as the wait goes on.

This is the trick that the best apps use, and most people don’t even notice. Instead of a static “Loading…” you show a sequence“Connecting to your account…” then “Pulling your data…” then “Almost ready…” The user has no way to verify these stages are real. Frequently, they aren’t the system isn’t actually doing those distinct steps in that order. But it doesn’t matter, because the changing text tells the brain that the system is doing real work. Something is happening. Progress is being made. The wait is going somewhere.

People will wait significantly longer with changing text than with a static spinner, even if the underlying wait is identical. This is one of the strangest, most useful pieces of UX psychology I know. Changing language buys patience the same way movement does, because both are evidence that something is alive on the other end.

This whole strategy holds up to about ten seconds.

Text that changes buys patience that movement alone can’t. The brain reads “different words” as “real progress,” even when it isn’t.

Text that changes buys patience that movement alone can’t. The brain reads “different words” as “real progress,” even when it isn’t.

The ten-second cliff

After roughly ten seconds, the spinner is finished, and so is your user’s patience for it.

This is the cliff. Past this point, looped animations stop working. They don’t just lose effectiveness; they actively start hurting. The user has now been staring at the same circle, making the same motion for ten full seconds, and instead of reassuring them that something is happening, it starts feeling like proof that nothing is. The spinner becomes a symbol of being stuck. Every additional second past ten makes the frustration worse, not better.

Past the ten-second mark, you need a fundamentally different approach. A real progress bar, if you actually know how long the wait is. A step-by-step indicator with checkmarks as each phase completes. A message that explains what’s happening and lets the user feel oriented in a longer process. Something with structure, not just a loop.

I learned this the painful way back in school. I was running a simulation for a robotics project, a group quiz, the kind where points are on the line, and everybody’s eyes are on the laptop, and the thing just hung. The little indicator kept moving, the laptop didn’t formally freeze, but it sat there spinning for what felt like a year. I had no idea if it was about to finish or had silently died. My group had no idea either. We sat there watching a spinner, sweating, with no information and no recourse, slowly losing confidence not just in the laptop but in our entire approach. It almost cost us a point.

In hindsight, the spinner was doing exactly the wrong thing for the situation. We needed a progress bar, some indicator of how far through the simulation it actually was. The spinner could only tell us, “I’m doing something.” We needed to know, “and here’s how close I am to being done.” Past about ten seconds, the difference between those two messages is the difference between patience and panic.

The rule: after ten seconds, looped animation isn’t a loader anymore. It’s a question mark.

And if it actually fails, don’t make them wait for the bad news

One more piece, and it’s the one I see violated most often.

If something is going to fail, show the error immediately. As soon as the system knows. Don’t make the user watch a spinner for fifteen seconds and then politely inform them the action didn’t work. That’s not “showing a loading state.” That’s making the user wait for free, and then handing them bad news as the reward.

A failure detected at second two should be shown at second two. The user has more patience for a fast failure than a slow one. Counterintuitively, an error that arrives quickly often gets a calmer reaction than the same error that arrives after thirty seconds of waiting. Quick failure feels like the system is honest. Slow failure feels like the system was lying to you the whole time.

This is also the part where AI-generated code falls down constantly, and it’s worth flagging if you’re vibecoding any of this. The AI will often build the happy path with a beautiful spinner and forget to plumb in the failure path entirely, so when something goes wrong, the spinner just keeps spinning until something else times out. You sit there watching nothing, and the app never tells you anything went wrong. From part one onward, this has been the trap: the AI builds the success state and ignores everything else. The error state isn’t optional. It’s the half of the user experience that decides whether people trust your app.

The full timeline, on one page

The thing I genuinely wish someone had handed me back when I was first learning this:

  • Under 1 second — show no spinner. Just show the result.
  • 1 to 5 seconds — a plain inline spinner is enough.
  • 5 to 10 seconds — add text. Changing text if you can. Static text if you can’t.
  • Over 10 seconds — kill the loop. Progress bar, step-by-step indicator, or real status updates.
  • Failure? — show it the second you know. Never make the user wait for bad news.

Every interaction in your app fits somewhere on that line. Most apps pretend the entire range is just “show a spinner forever.” It isn’t. The right loader at second one is the wrong loader at second eleven, and the difference between an app that feels responsive and one that feels broken is whether you noticed the cliff.

Every app has a number — the second past which the user quietly decides to leave. Most apps don’t know what theirs is.

Every app has a number — the second past which the user quietly decides to leave. Most apps don’t know what theirs is.

Where we’re going next

Speaking of failure, that’s where this series is heading next.

Errors are the loaders’ angrier cousin. Everyone builds them last. Nobody tests them properly. The AI seldom writes them well. And the difference between a good error state and a bad one is, genuinely, the difference between a user who tries again and a user who closes the tab forever.

In part five, we’re going to talk about error states. What they should say. What they absolutely shouldn’t. How to write one that helps instead of hurts. And the strange psychological move that turns a moment of failure into one of the strongest trust-building moments your app has.

The loading state is what your app says while it’s thinking. The error state is what it says when it’s wrong. Most apps get neither right.

Come back for part five. I’ll show you how to get one of them, finally, right.


메타데이터
post_id
ce9e860ec7fa
slug
how-long-people-will-actually-stare-at-a-spinner-before-they-quietly-leave-ce9e860ec7fa
url
https://medium.com/tech-and-me/how-long-people-will-actually-stare-at-a-spinner-before-they-quietly-leave-ce9e860ec7fa
canonical_url
https://medium.com/tech-and-me/how-long-people-will-actually-stare-at-a-spinner-before-they-quietly-leave-ce9e860ec7fa
author_url
https://medium.com/@Asapteejo
status
ok
fetched_at
2026-06-09 15:37:30