1. Why Progress Bars Exist
I bricked a router waiting for a firmware update that hung at 99%. The bar wasn’t measuring completion. It was measuring my patience. That’s when I realized: progress bars are confidence games.
The progress bar was born in 1979 at Xerox PARC. It learned to lie around the time software started hanging at 99%.
That is the short version. The real story is longer and stranger. The original idea was simple: show how close the user was to finishing the load. Over time, the bar became a tool for managing boredom and trust, not only bandwidth.

2. The 99 Percent Problem
A familiar example is the installer progress bar. Game installers and OS updates show 0 to 100 percent, then sometimes sit at 99 percent because the expensive work happens at the end. At that point, users have invested too much time to cancel.
So why lie? Because honesty often feels broken. A progress bar may be partly disconnected from the actual loading process. It exists to show movement, reduce abandonment, and keep the user from assuming the app froze.
AI made this worse. Model loading, streaming tokens, and queued inference are hard to estimate cleanly. When ChatGPT shows “Thinking…” while text streams in, that is a hybrid signal: you see activity, but not a reliable completion percentage. A 100B parameter model can hang at the final percent for minutes.

3. Before Progress Indicators
3.1 Life Before Feedback
Before progress indicators, software just froze. Batch jobs ran silent. You couldn’t tell if the app was working or hung, especially on machines with spinning disks and no SSDs. If you used legacy software, you remember mashing keys to see if the cursor would blink.
3.2 The Early Signals
Then came static text. “Loading…” or “Please wait.” No bar, no percentage, just a promise that something was happening.
Primitive counters followed: simple loading bars based on operations completed. If the app started with a bunch of quick checks and later hit larger tasks, the bar would jump instead of moving steadily.
That was still better than a frozen screen, but it gave only partial insight. Mostly, it helped users feel less abandoned.
4. The First Real Bar
4.1 Pre-Digital
To correctly tell the history of the progress bar, you must tell the story of Gantt charts and earlier harmonograms. These acted as a pre-digital progress bar for factories and other projects.
4.2 The Start
In 1979, Mitchell Model at Xerox PARC added a graphical bar to the monitoring system. Following in 1985, Brad Myers wrote a paper called “percent done progress indicators” in which he showed that progress bars reduce user anxiety even when the computer isn’t fast.
4.3 Why This Moment
Developers noticed users abandoned slow software. The bar didn’t make loading faster; it made waiting tolerable.
5. From Bars to Spinners
This is the era where progress bars take one of two paths: Determinate or Indeterminate.
5.1 Determinate
A Determinate system has a real denominator (bytes, items, frames, etc.) so the percentage implies actual completion.
5.2 Indeterminate
An Indeterminate system is one that cannot estimate total work; it can only tell that something is in progress, like query planning, remote calls, or cache warm-up.
5.3 Spinners, Throbber, & Cursors

Mosaic and Netscape used animated logos as throbbers for loading indicators. The logo pulsed when busy and sat still when done. They would also use the OS cursor when possible: the flipping hourglass, spinning pinwheel, or tiny circular blue spinner.
A common trick is to start with an Indeterminate spinner, then switch to a Determinate progress bar once the app has a real denominator. Worse apps switch to a fake Determinate bar with a scripted percentage sequence.
6. Why 99 Percent Never Ends (Under the Hood)
6.1 Why the First 90% Is Fast
Indeterminate spinners keep you engaged. They mimic motion without promising completion. The more interesting problem is Determinate progress. The first 90 percent is often copying files, processing common cases, and straightforward I/O.
The expensive work arrives late: verifying checksums, updating registries, cleaning up, and waiting for remote acknowledgments. Some of that is long computation. Some of it is worse: waiting on servers.
6.2 The Lie of Estimation
It’s not quite a lie; it’s a statistical guess. Installers estimate from average runtimes or step counts. They don’t mean to deceive, but they’re vague guides at best. The two common ways to create a Determinate bar are to use a timer from the average time to install, or to use steps completed to move the bar based on the amount completed. Most people assume step-count bars are more common, but they feel jumpy and random. Some installers combine both: an average time estimate plus step counts. That is how you get a bar at 99 percent with the timer at zero while the install still has unfinished work. Sunk cost does the rest. Users refuse to quit because they feel almost done, and every extra minute makes abandoning the wait feel worse.
6.3 Tricks of The Trade
An honest progress bar would feel jittery with pauses, sometimes moving backwards. This would make the user feel like the bar was broken. So, this is where developers use a technique sometimes called “benevolent deception”; research from Harrison’s “Faster Progress Bars” and “Rethinking the progress bar” shows that easing curves and visual tricks make bars feel faster without changing duration.
I tried building an honest bar once. It showed a download dropping from 60% to 45% when a CDN node failed. Our support tickets spiked 400%. Users don’t want honesty. They want confidence. I learned to clamp backwards progress and hide the jitter.
Other tricks include moving quickly at the start, when the user is least invested, then slowing near the end. Another common trick is giving more visual space to predictable phases so movement seems consistent. A good progress bar also clamps backwards progress. That may make the bar sit on one number longer, but backwards movement is more disruptive than a longer pause.
7. How Waiting Feels
7.1 Humans are bad at gauging time
We feel the present intensely and discount the past and future. An unoccupied wait feels longer than a busy one, even when the clock says otherwise. If the user sees movement and has something to track, the wait feels shorter, even when it is not. Myers proved this in ‘85: users preferred bars even when the computer wasn’t faster. They felt better about the system. Later, Harrison showed you could manipulate perceived time with easing curves. I used his paper to justify a bar that went backwards in my first startup. It failed. Users don’t read papers.
Research corner
Myers (1985) on percent-done indicators, Harrison et al. (2007) on rethinking progress bars, and Harrison, Yeo, Hudson (2010) on faster progress bars provide the key HCI evidence backing these perception effects.
7.2 Ethics of Perceived Performance
Manipulation in UX can serve users or exploit them. The difference lies in intent and outcome.
Good manipulation helps users tolerate necessary waits:
- Chunking: Step counts break a long wait into visible stages (“Uploading”, “Processing”, “Finalizing”) so users get multiple mini completions.
- Microcopy: Short labels explain what is happening, reducing “is it stuck” anxiety.
- Gentle motion: Subtle ribbing, pulsing, and non-hectic animation make time feel smoother.
Netflix, for example, loads the app behind its boot screen. By the time you see the UI, it’s ready.
Bad manipulation exploits users for engagement metrics:
- Fake stages purely to distract
- Bars that are mostly timers with no correlation to actual loading
- Time estimates that don’t even try to be accurate
In many cases, teams trade raw accuracy for perceived stability under real uncertainty, not just for engagement metrics.
8. Skeletons & Shimmers: The Modern Meta
8.1 Skeleton Screens
As hardware got faster, users got less patient. Skeleton screens show the shape of a page before the content arrives. They make the app feel like it started, even when it hasn’t.

A shimmer animation makes the skeleton feel active. Combined with the rough shape of the page, it tells the user the app has started instead of freezing on a blank screen.
Skeletons and shimmer are now the default loading pattern for feeds and dashboards. The plain progress bar still has a job when the work has a real finish line: upload, download, install, export.
8.2 The Mobile World
Mobile killed the progress bar. Pull-to-refresh turned loading into a gesture. The feed killed “done.” Now infinite scroll trains users that progress is a lie.
Every app and web app has little circular progress rings around icons, often with a Determinate fill and an Indeterminate spinner combined. For a lot of people, this is now the most common progress indicator they see.
8.3 Infinite Scroll
We live in the age of the infinite scroll. Feeds replace “done” with “more below.” Progress moves from explicit bars to implicit motion: as long as new content appears, the app feels fast enough.

9. Ways to Use Progress Indicators
9.1 How to choose an Indicator
If you can, use a real Determinate percent bar when you have a stable denominator: bytes, items, frames. If those are not available and you need an Indeterminate option, reach for spinners and skeletons with shimmer. Prefer honest native UI like the HTML <progress> element when it fits. It tells the user the app is alive without pretending to know more than it does.
9.2 Keep the User Engaged
- Keep messages short, specific, and honest.
- Avoid fake precision like “3 seconds left” unless you really know.
- Use easing and subtle animation to hide jitter, not to fabricate progress.
- Do not make the loading indicator the center of attention. Avoid aggressive flashing or high-stress motion.
9.3 Trust & Ethics
Users have learned to distrust progress bars. If you build one, you start from skepticism. Under-promise. Explain real blockers. Do not show “3 seconds left” unless you actually know. If you must block the UI, explain why and make it rare. When in doubt, promise less. Follow accessibility patterns like the ARIA progressbar role so the indicator stays perceivable.
10. Trust in the Line
Progress bars sit in an awkward spot: users suspect they’re fake, and developers know they can’t be fully honest. They’ve become a necessary fiction anyway.
They bridge unpredictable systems and humans who hate waiting blind. A good progress indicator respects uncertainty without disguising it. By the time a bar hits 99 percent, it is no longer measuring completion. It is measuring how much patience you have left.
The last time I trusted 99 percent, I lost a router. Now I design for the moment after the user realizes the bar is lying. Give them a way out.
Jonathan Reed · Contact
Citations
- Historic Projects. “The Harmonogram.” The Harmonogram
- Gantt chart background and early project scheduling context.
- Mitchell Model, PARC memo (1979), and early graphical progress indicator context.
- Myers, B. A. (1985). “Percent-done progress indicators.” CHI ‘85. ACM DL: Percent-done progress indicators
- Harrison, C., et al. (2007). “Rethinking the progress bar.” UIST ‘07. Author PDF: Rethinking the progress bar
- Harrison, C., Yeo, Z., Hudson, S. (2010). “Faster Progress Bars: Manipulating Perceived Duration.” CHI ‘10. Chris Harrison
- Browser throbbers and animated browser activity indicators.
- Wroblewski, L. (2013). “Skeleton screens.” LukeW. LukeW
- Brichter, L. (2009). Pull-to-refresh in Tweetie.
- HTML
<progress>element. MDN. MDN: HTML progress element - ARIA progressbar role. MDN. MDN: ARIA progressbar role
- Hero Loading Bar, Data Loading, Activity Tracker, Buffering Meter, Completion Gauge PNG, locally optimized from PNGMART.
- Determinate loading bar GIF, locally optimized from Wikimedia Commons: Barralgoogog
- Circular loading spinner GIF, locally optimized from Wikimedia Commons: Loading icon
- Skeleton screen loading GIF, locally optimized from Dribbble