The Beach Ball of Death and Other Ways We’ve Lied to Users for 40 Years
Part two of a series on building software people don’t quietly hate. Last time: the difference between how an app looks and how it feels…
The Beach Ball of Death and Other Ways We’ve Lied to Users for 40 Years
Part two of a series on building software people don’t quietly hate. Last time: the difference between how an app looks and how it feels. Today: the humble loading state, and why the spinning thing on your screen is one of the oldest tricks in software.

Forty years of staring at a screen, waiting for something to happen. The indicator changed. The waiting didn’t.
In part one, I told you about a freshman-year CS major whose app teleported you to the wrong page every time you clicked and occasionally died on the spot. The lesson was simple: working code and good software are two different things, and the gap between them is where users quietly give up.
This time, let’s zoom all the way into that gap and look at one specific screen state that almost everyone building software in 2026 forgets including the AI tools half of us are now building with.
The loading state.
Every screen you build secretly has four states, not one. There’s the happy path, everything loaded, everything’s perfect, this is the version you design first and the only one most people ever build. Then there’s loading, the moment between asking for something and getting it. It’s empty when there’s nothing to show yet. And there’s error when it all goes wrong. Forget any of these, and your users will notice. They won’t always know what’s missing. They’ll just feel that something’s off.
Today we’re doing loading. And to understand why it matters so much, we have to go back forty years because humans have been staring at “please wait” since before most of us were born, and the history is genuinely wild.
A short, slightly embarrassing history of making people wait
In 1984, the original Macintosh had a problem: sometimes the computer was busy, and the user had no idea. So Apple gave us one of the first loading indicators, a tiny wristwatch cursor. That was it. A little watch. No animation, no spinning, no progress. Just a watch sitting there, silently implying, give it a minute, pal.
Windows showed up in 1985 with its own version: the hourglass. Same energy, different metaphor. Also, no animation. And astonishingly, that frozen little hourglass stuck around for roughly twenty years. Two decades of staring at a static hourglass, wondering if your computer was thinking or had simply given up on life.
Then, in the late 80s, someone had a genuinely good idea: the progress bar. For the first time, the computer wasn’t just saying I’m busy, it was saying I’m busy, and here’s roughly how busy. A bar that filled up. You could watch it move. You knew, more or less, when the pain would end.
And here’s the part I love. Research from around that time found that something like 86% verify this number of people preferred progress bars even when the bar wasn’t accurate. Read that again. People liked the bar even when it was lying to them. A bar that crawled to 90% and sat there, or jumped from 30% to done, people still preferred it to no bar at all. Because the bar wasn’t really about precision. It was about reassurance. It told your brain: something is happening, you have not been abandoned, sit tight.
That’s the whole secret of loading states, hidden in a 30-year-old study. They’re not about information. They’re about trust.

A watch in 1984, an hourglass in 1985. For decades, “please wait” was the entire conversation.
The beach ball of death
Then came 2001, and Mac OS X, and the thing I will hold a grudge against forever: the spinning rainbow wheel. Officially, it has a polite name. I call it what everyone I know calls it: the beach ball of death.
I have a very specific memory of a progress bar trying to end me.
It was a deadline, one of those submit-by-11:59-or-it ’s-a-zero situations, and I was uploading the assignment with about four minutes to spare, which by student standards is practically early. The upload bar climbed. 60%. 75%. 84%.
Then it just… stopped.
It sat at 84% like it had decided that was a fine place to retire. And I sat there sweating, doing the math on whether I was about to eat a zero because of a frozen rectangle. Did it freeze? Is it still going? Is 84% where uploads go to die? I didn’t dare close the tab, because closing the tab might mean starting over, and starting over might mean missing the deadline. So I just stared at it, bargaining with a progress bar like it was a hostage negotiator.
It did submit. Eventually. But here’s the genuinely infuriating part, and the reason I’m still annoyed about it years later: the interface never told me. There was no “upload complete,” no checkmark, no green anything. The bar hung, and then the page just moved on, and I had to go hunt through my submissions to confirm I hadn’t failed. The upload worked. The UX was a disaster. It manufactured five full minutes of panic for no reason other than nobody bothered to build the part that says “you’re fine, it went through.”
That’s the beach ball’s whole crime, just wearing a different costume. It made me wait, told me nothing, and let me assume the worst.
The beach ball was animated, which felt like progress. It spun! It had colors! But it committed the cardinal sin of loading states: it told you absolutely nothing. Has it been spinning for five seconds or five minutes? Is the app thinking, or is it gone forever, and you should start saying your goodbyes? No idea. The beach ball spins exactly the same whether your file opens in two seconds or never. It’s a loading indicator that loads you with pure existential dread.
And technically? It still exists today. You just see it less, because hardware got fast enough to hide it. The beach ball didn’t get fixed. We just got powerful enough to outrun it most of the time.
The plot twist: skeleton screens
For a long time, the spinner was the best we had. A little circle going round and round, doing the beach ball’s job but smaller. Better than nothing, but still basically saying trust me, something’s happening with zero detail.
Then, in 2013, a designer introduced an idea that quietly changed how modern apps feel: the skeleton screen.
You’ve seen these everywhere, even if you’ve never had a name for them. Open Instagram on a slow connection, and before your feed loads, you see grey boxes and lines roughly where the photos and captions are about to appear. That’s a skeleton. Facebook was one of the early big adopters, and once you notice them, you see them in nearly every app you use.
Here’s why they’re brilliant, and it’s a genuinely clever bit of psychology. A spinner makes you wait and then see the layout. A skeleton lets your brain start processing the layout before the data even arrives. By the time the real content loads in, your eyes already know where everything goes, so the page feels like it appeared faster, even when it didn’t. You’re not waiting for the page anymore. You’re watching it become the page.

A skeleton shows you the shape of what’s coming. Your brain starts reading the page before the page exists.
A skeleton screen is the polite opposite of the beach ball. The beach ball hides everything and tells you nothing. The skeleton shows you the shape of what’s coming and lets you settle in.
So, when do you still use a spinner?
Skeletons aren’t a total replacement, and this is where I see people overcorrect once they discover them.
Skeletons make sense when you’re loading a layout, a feed, a list, or a page full of content with a predictable shape. But a lot of loading happens in small places where a skeleton would be absurd. The little spinner inside a button after you hit “Submit.” A small region of a page is refreshing. A single action processing. You don’t draw a ghost layout for a button, you just spin a tiny circle so the user knows their click landed.
I learned this the embarrassing way, and recently.
I was vibecoding the student records section of a school management system, describing what I wanted to an AI and letting it generate the screen. It worked, and it even added a loader on its own. The problem was the loader was wrong for the job. It dropped a single spinner on a page that loads a whole table of student records, so while the screen sat there empty, all you got was one little circle spinning in the void. It looked perfect in the demo, where the data loaded instantly. The first time it hit real records and actually had to wait, the whole app felt frozen and slow, like nothing was happening at all.
That page wanted a skeleton screen to show the shape of the records table, let the eye settle, and fill in the rows when the data arrives. The AI gave me the laziest default it had: a spinner, in the wrong place, doing the wrong job. So I did the thing I keep coming back to in this series I stopped vibecoding, brought my actual software engineering knowledge to the table, and fixed it myself. The AI got me a working screen. It took an engineer to make it not feel broken.
That’s the trap from part one, reincarnated. The AI builds the happy path and reaches for the most generic loader it knows. I’d asked it to build the screen I hadn’t told it how the screen should wait, so it guessed, and it guessed wrong. If you don’t know the difference between a spinner and a skeleton yourself, you’ll never catch the moment it hands you the wrong one.
The point isn’t skeletons good, spinners bad. It’s that they’re tools for different jobs, and reaching for the wrong one is its own kind of bad UX.
The thing that ties forty years together
Here’s what forty years of wristwatches, hourglasses, lying progress bars, beach balls, and skeletons all add up to:
A good loading state is invisible. A missing one is loud.
When loaders are done well, you genuinely don’t notice them. You hit a button, something acknowledges the tap, the content shows up, and your brain never flags it. People will wait noticeably longer without frustration when they’re given a good loading state the progress-bar study proved that decades ago, and skeleton screens prove it every day on apps you use without thinking.
But leave the loading state out entirely, and your user clicks a button, sees nothing happen, and immediately assumes the thing is broken. This is exactly what happened with my freshman friend’s app in part one. You’d click, and the app would just sit there, silent, and you’d have no idea if it was working, frozen, or dead. No feedback feels identical to failure. The user can’t tell the difference between “loading” and “broken” unless you tell them.
And this is the part that makes loading states urgent right now. I vibe code a lot. I’ll describe an app to an AI and ship it fast, and I can tell you the loading state is one of the very first things these tools skip. They build the happy path, the screen where the data is already there. They almost never build the screen for the half-second or five seconds before the data arrives. So if you’re building with AI and you don’t ask for it specifically, you’re shipping my friend’s app. Beautiful, functional in the demo, and silently terrifying the first time the network takes a breath.
Where we’re going next
So that’s the loading state, the forty-year-old trick for telling users you have not been abandoned. We covered the why. Next time, we get tactical.
In part three, I’m going to break down which loader to use where, because the skeleton, the spinner, and the progress bar are not interchangeable, and using the wrong one is a mistake I see constantly. When does a skeleton actually help, and when is it overkill? When is a spinner the right call? When do you owe the user a real progress bar instead of a vague spinning promise? We’ll go through it, case by case, so you walk away knowing exactly what to reach for.
Forty years ago, we gave people a tiny watch and hoped they’d be patient. We can do a lot better than that now. The tools are sitting right there.

Done well, a loading state buys you patience the user never notices giving. Done badly, every second feels like the app died.
We just have to remember to use them before the AI hands us a beach ball, and we ship it without looking.
Come back for part three. I’ll tell you exactly which loader goes where.
메타데이터
- post_id
- 6cd1bf1d4383
- slug
- the-beach-ball-of-death-and-other-ways-weve-lied-to-users-for-40-years-6cd1bf1d4383
- url
- https://medium.com/tech-and-me/the-beach-ball-of-death-and-other-ways-weve-lied-to-users-for-40-years-6cd1bf1d4383
- canonical_url
- https://medium.com/tech-and-me/the-beach-ball-of-death-and-other-ways-weve-lied-to-users-for-40-years-6cd1bf1d4383
- author_url
- https://medium.com/@Asapteejo
- status
- ok
- fetched_at
- 2026-07-13 06:23:13