Hacker News new | past | comments | ask | show | jobs | submit login
Progress bars still lie (utk.edu)
201 points by pavehawk2007 62 days ago | hide | past | favorite | 227 comments

Progress bars are something that have been researched and iterated on for decades now, and the overall sentiment is pretty clear – users like seeing numbers go from zero to a hundred while they wait. It doesn't matter if they aren't always accurate. Replacing them with a static "processing" message would absolutely increase user confusion and dissatisfaction with loading times.

A while ago we put in a lot of engineering effort to build a good progress system for a heavy, multi-step background task to show to our users, and the overwhelming feedback was - "it always gets stuck on a certain percent", "it is too slow" and "it is unreliable". After feedback from design we hard-coded it to a steadily increasing bar regardless of actual progress, and the complaints all stopped immediately.

As another commenter pointed out, static "processing" messages are indistinguishable from "your system is hung".

I think the best option is simply X/Y bytes downloaded, like Blizzard does on WoW patches. The fraction indicates how much is left to download, and the rate of the numerator changing informs how quickly the download is going.

> As another commenter pointed out, static "processing" messages are indistinguishable from "your system is hung".

This is an important point. "Lying" progress bars are still conveying essential information - that the installation is progressing and isn't frozen. I remember from my days working with W98 and early Ubuntu versions, one of the most important bits of information coming from progress bars was whether or not the whole thing was frozen and needed the power cord pulled.

I've seen Google display progress bars showing that my page is loading, even when I've totally lost internet connection and I know it will never load. The progress bar goes as something like 1-e^-t, so it just asymptotically approaches 100% but never gets there. When it's that kind of lie, I don't think it's conveying any essential information.

The "system is not hung" signal is dead now due to modern platforms making sure that nothing happens on the UI thread. Now we get buttery smooth 60 fps spinners and loading bars, but if the thread doing the real work hangs, there's no indication.

Exactly this. And spinner gifs are particularly useless, because they're that - gifs. Not progress indicators that need to be explicitly told by code to spin a bit more. Just fire-and-forget animations, that will keep to spin forever even if your processing code dies.

Even worse than not conveying information, it diminishes your user's trust in your product if they realise the progress bar is bullshit.

Totally agree. I was rather intentionally using examples from more than a decade ago, where I was using the progress bar to observe whether or not the whole system was hung.

This was back when my best computer had a 500 MHz CPU and 512 MB of RAM.

<fixes his glasses> There was never a time when

>best computer had a 500 MHz CPU and 512 MB of RAM

500 MHz cpus started showing up in servers with 21164 in 1996 in boxes maxing out at 2GB ram, and on desktops with 1999 Pentium 3 plugged into 1998 chipset (440BX) already supporting 1GB.

I didn't say I wasn't a broke kid at the time. ;)

Really all you need is 32 KB of RAM


Will Google pick up the connection again when it's available? And could that theoretically happen at any moment?

If so, it doesn't seem completely unreasonable to communicate in this way. (I agree it could be communicated better)

The system is not quite hung, but it's not doing great.

I had disconnected my router, so I don't think Google was going to pick up the connection again.

At the very least, there's no sense in which the page loading (or map route finding, etc) was farther along at t=2 than it was at t=1 when the connection was removed, so for Google to be telling me it's making progress in that situation is a transparent lie.

Unless the information they're trying to convey with the progress bar is simply that "time is passing", which I'm well aware of.

IE6 also did this back in the day, it was infuriating.

UI toolkits include "indeterminate" progress bars. Back before AJAX spinners (really, a simplified form of indeterminate progress bars) took over, they were a blob that bounced back and forth, or scrolled left to right repeatedly, within the progress bar's trough. Sometimes, a barber pole. The good ones would only advance the animation so long as actual progress was occurring, so that a hung system was indicated by a hung animation.

There's no reason to lie.

The problem with AJAX spinners is that they’re often just GIFs or CSS animations that will keep on playing even if “the system has hung” (e.g. the AJAX request failed and there’s no client-side error handling logic, no retry, no error display, and no UI cleanup) so in that respect the situation now is worse than it was before.

Yes, I agree with that for the case of AJAX spinners. A lot of web software fails to handle errors (resulting in the AJAX spinner spinning on — I think we've all seen this all the time¹) and most don't connect progress events to the animation in any way. There's no reason web-based libraries couldn't provide utilities for that, other than they don't, the existing code is of poor quality, and the APIs that browsers provide don't really push one towards the high-quality solutions in any way (since you really have to either get this level of functionality from some sort of library, or build it yourself).

My point is that good UI is possible, there is even precedent for it, and that while we definitely need to do better perhaps with available APIs or tooling, that is not an excuse for the moral failing of lying to the user.

¹and I'd say that's even the mild case. A number of high-profile websites that encounter even edge cases — not even errors — just simply fail to render at all.

Well, not necessarily, if the GUI with the progress bar and the installation or whatever are on seperated threads.

That's true on the backend, but it doesn't help the end user much, since they don't know that.

Heh, I've imagined a message like:

"Your task has started and is processing in the background where it can't be observed. Please wait."


You're bringing up the easiest use case though. Most complex flows cannot be easily expressed by a single determinable metric.

Complex flows can be represented by a tree control full of checkboxes that tick off for things that are done, which can be hidden behind a "show details ..." button next to a regular progress bar. If the users can see the detailed tasks, maybe they will be less ticked off by a jumpy progress bar.

A tree is insufficient for flows at $dayjob, you need a directed acyclic graph to handle fanout/parallelism.

For which a visualization exists internally, but every time someone decides to "fix" the progress bar problem they do a one-off analysis and only wire up the three biggest steps to the bar.

If you can reliably break down your complex flow into a tree of checkboxes, you could just as easily render a truthful progress bar based upon how many sub tasks are done.

Yes, but that bar would still get hung intermittently whenever a specific task took a long time.

How is the checkbox thing any different? If one task blocks progress, the tree also doesn't update

At least I know what it is doing at the moment its blocked (and in many cases I can tell whether that is justified to take N time or not).

With a progress bar I don't know anything.

I don't know whether it _will_ be any different, but there was some speculation about that:

> If the users can see the detailed tasks, maybe they will be less ticked off by a jumpy progress bar.

Context. You see not just the thing currently executing, but also the things remaining to be executed - which allows you to mentally gauge which of them may slow down.

Or just show verbose logs like Apt GUI frontend.

Problem with just logging the progress is that the user has no idea where he "bottom" is. A log might as well be a spinning cursor or any other animation.

It's invaluable from a troubleshooting perspective, though. "Hmm, it always seems to get stuck when installing this particular package"

This is the most infuriating part of progress bars to me. When it hangs I don’t even have a jumping off point for Google. I can only search “foo hangs during install” which almost always results in issues that are not the problem I’m experiencing because usually the most common reason isn’t the reason the majority of the time. “Foo hangs during ‘reticulating splines’” usually has far more useful results.

Had problem when GUI closed after trying to install a package. No error, no logs. (or was it defaulting to the normal state with install button and no logs, I don't remember)

Found out about package conflict only after running apt from the terminal.

if you give numbers of any sort, users will try to mentally do the math to convert that to a percentage -- and at that point, you might as well give them a progress bar.

If you instead just show a description of the current task, users will want to know how many tasks are left. if you tell them how many are left, they will revert to thinking of it as an overall percentage.

i'm a fan of "checklists" that get ticked off as the process progresses; possibly with progress bars for specific tasks, if they have a straightforward way of measuring that (like % downloaded). but i almost never include an overall progress bar for a multi-step process. it keeps the user's focus on the current task, while still providing some information about what's to come.

That works for completion status, but I don't think it works for task failure notification. Do you know of any clever way that reliably informs the user whether or not the process is frozen?

Alternatively you can flash actions on the screen, even if the user cannot read or understand what these actions correspond to, it conveys the message that work is being done (it’s not hung) without lying on how far you think we are into the process (if you don’t have that visibility).

I bet $100 Netflix does the same. From my "experiments" during outages, it seems to show you a timer based progression from 0-25% no matter what, while it waits for stuff to queue/load properly, then it takes off to 26-100% in short order.

So when it Netflix is up, it slowly climbs 1-5% then rockets to 100% and plays.

When it's slow, sometimes it goes to 15%, then rockets up.

When it's down, it reaches 25% after 12.5s or whatever it is, then sits there forever/shows an error message.

Yea I've noticed that as well. If it stops on 25% then I know something is broken over at Netflix. If it stops at any other number then it's just something being slow, but will start eventually.

When my internet connection is down I get 99% sometimes from Netflix. I typically use the PS4 client so maybe that’s the difference.

It's actually representing the users patience level and reflecting that back at them like a mirror.

Lying often reduces complaints. This doesn't mean users like being lied to, it means they don't know they are being lied to.

Users aren't being fooled here. People learn that progress bars aren't accurate, and things like the author mentioned, "when it gets to 75% it will really be done".

First, no, as the other comments here attest, the end result of constant lying is that nobody trusts progress bars at all; if things reliably finished at 75%, progress bars would be easy, but they don't so they aren't. Second, that people soon get used to being lied to does not make lying OK.

I don't think you are in disagreement.

Neither of Jeremy Bank's sentences are relevant to my first comment if you try to contort their interpretation so they do not conflict with me.

To me, JeremyBanks' second sentence clearly implied that users don;'t trust progress bars anymore, and your comment was unnecessary. He is also certainly implying that lying is not OK. Interpreting them otherwise seems like a strange kind of contortion to me.

I think you're clearly misinterpreting, but it's not worth discussing. JeremyBanks can clarify for himself if he wants.

"After feedback from design we hard-coded it to a steadily increasing bar regardless of actual progress, and the complaints all stopped immediately. "

Are you talking about progress bars, that go steadily up to 99 or 100% and then stay there, until the actual progress is done? They can cause big frustration, too ...

The trick is to smoothly animate the filling of a random percentage of the remaining unfilled bar between, say, 30% and 70%, with the timing of the advancements themselves slightly randomized. A sort of Zeno’s progress bar. It will neither peg at 100 nor shoot past, and the pulses feel “organic”. Bonus points for advancing the bar to known fixed points of progress when real feedback is received.

The amount of complexity needed to lie to the user this way is becoming comparable with the amount needed to do the job right in the first place.

The approach for this is to simply restart the bar from 0% and display some bogus message implying it is now doing another task. Always keep moving.

Oh yeah, I love those equally. Getting hopes up - to finally crush them.

Reticulating Splines

The Sims (1, at least) had a fixed set of startup messages, in the same order each time.

At my first job we made training simulations. One day someone decided to do make our loading bar more accurate by splitting loading into several segments and keeping a local record of the average time to load each segment. The result was a smooth progress bar from 0 to 100. We were proud of it.

Years later I worked on a popular AAA franchise and we had replace our loading screen spinner with a progress bar due to console requirements. We simply estimated a worst case scenario and made the bar driven by a timer from zero to this number, smoothly speeding towards 100 when loading was done. People kept complaining that something felt off and it didn't seem reliable.

The failure mode becomes the bar stops at 99 or 100 but the game doesn't run, or worse, the bar flies off the end of the chart, hitting 101%, 102%, etc...

Neither of those could happen since it was capped at 100 and the time to fill it was just below the timeout.

Neither could happen if nothing went wrong. What if there is a hardware issue that makes it much slower at reading data than usual, like excessive CRC failures that require loads of retries to get a good read?

> After feedback from design we hard-coded it to a steadily increasing bar regardless of actual progress, and the complaints all stopped immediately.

This seems like a surefire way to end up with a progress bar at 8675309%, or a progress bar that gets to 100% and then sits there waiting for reality to catch up. And I say this from experience, having seen both of these failure cases numerous times in the wild.

If users are frequently reporting that the application's getting stuck at a particular percent, then - to me at least - that's valuable information for whether I should consider doing some optimization to speed up whatever step in the process corresponds with that progress percentage, or to break down that step further into smaller steps to keep things moving, or both.

This is because when I was growing up (Windows 95 era), it was normal for a computer to just completely freeze regularly. If I saw a static "processing", I'd assume the computer froze and would rip out the power after like 5 seconds.

Is the bar exceeds 100% in worst case?

Proposal 1 is the thing I want.

Please just list out a total number of steps and log when each of those steps is completed (with a short message describing what the step is so that we don't end up back on square one with fractional progress bars). If possible make the steps granular enough so that a step can be completed in under a second (so this may be hundreds or thousands of steps depending on the task length). In the case of say "bytes currently downloaded" this becomes essentially a continuous stream of steps (which is a good thing!).

First and foremost what this communicates to users is that the system is doing something useful. This is what frustrates me about spinners. They are functionally indistinguishable from a frozen system, to the point now that users synonymously identify an indefinitely spinning spinner with a frozen system. And progress bars that asymptotically approach completion even when the program is frozen have trained users to be similarly suspicious of progress bars.

Secondarily it offers the same vague assurances as a progress bar about approximately how much time is left. If you see 250 GB out of 500 GB downloaded you'll assume that you're half-way there, similarly if you see 250 steps out of 500 completed. Especially in the case of the latter, there's no guarantee that the total elapsed time is already 50% over, but that's true of progress bars as well.

Finally, if something goes wrong, there's usually a useful error message that can be shown since there's the context of all the previous steps that led up to this error.

I think there's two issues here that are often wrapped up together: 1. what is the status of my task, and 2. did the computer get stuck

If we could be sure the computer wouldn't get stuck (which is just a bug), then progress bars and spinners would be fine. If the task is as granular as you suggest, progress bars would be a great visual indicator, much better than text.

But since computers do get stuck, additional indicators should help with that. A spinner is supposed to show that a process isn't stuck, but those are fallible too. A textual representation ("bytes currently downloaded") sounds like a great addition to a progress bar. I've seen this a lot on linux distro installers, where you can click "details" below the progress bar to see the console output.

I'm so sick and tired of seeing spinners that keep spinning, even after the process failed; this is an epidemic in web apps, where failures are often a bit too graceful and application state is silently corrupted.

About 15 years ago a coworker had a spinner that was an animated gif, When I see people doing font awesome spinners it reminds me of that gif and I get just as angry.

Maybe there should also be a "seconds since last progress update" counter. In case of a download it gets reset every time a new packet arrives.

> But since computers do get stuck, additional indicators should help with that.

They need to be trustworthy. For that, they need to be wired directly into the process doing the work. So no spinner gifs that are animated by the browser/renderer, and can spin forever even if your application dies. It needs to be something where any visual change is directly related to the operations you're monitoring.

That's why a list with textual descriptions of step is a great idea - it's literally too much work to implement it in a way other than the actual completion of a step displaying/ticking off a corresponding label. So seeing that, I'd know the software isn't lying to me.

How about a progress bar that you can expand into a more itemized status presentation-- either a list of tasks or even a log of exactly the last task started and when it was done.

Itemizing individual steps allows users to reason about their performance characteristics, if well explained. These might cause jerkiness in the overall bar.

If I had a progress bar stuck at 27%, it would be valuable to click a little "view more" link and see "11:34 AM: begin downloading file 27/100: foo.tgz (62.3Gb)" I'd be more willing to expect to wait on it advancing than if it was a 30k file.

yes. i think this is done by the Ubuntu software updater app.

I actually don't mind the occasional lying progress bar. I think TurboTax is famous for this, where they just toss in fake progress bars to indicate that they are crunching some numbers, which really just take milliseconds, if that. The goal is just to convey that "heavy work is happening".

I ended up using this strategy recently because I wanted to convey that my app was "doing work on your behalf", so I tossed in a super quick progress bar like TurboTax does and then did a slick transition animation to show the results. It's "unnecessary" in that I could've just showed you the results, but I really wanted to convey that there was a sort of cause-and-effect in the system. Without that little bit of animation, it felt like that would've been lost.

When we built a real estate search site that worked on a more "lifestyle search" we had to do something similar. We could return results in about 250ms, but a large portion of beta testers gave feedback that it felt "shallow". Added a 4-5 second animation and loading bar, and people gave better feedback on the actual results, etc. Small sample bias? Maybe. But no one ever complained about the speed in the two years we ran it.

Having some kind of transition to visually indicate a change of state is fine. But that's not what TurboTax does; they have a progress bar that is insultingly superfluous, because there's already a "next" button.

It's worse. They seem to be intentionally slowing things down to make it look like the software is somehow "working harder" because to some people it justifies the high price. A progress bar that takes 5s or more to complete for an operation that actually takes under a second.

Hell, the standard everybody seems to have converged upon is a mendacious progress bar where the user is not told what the percentage refers to (e.g., total install time? Number of files processed? Data left to be copied?). The frontend developer could show changing Matrix glyphs instead and the widget would be functionally equivalent but without giving the user false impressions.[1]

Given that as a standard, it's difficult for me to find more outrage for Turbotax misusing this already mendacious widget.

1: Some smarty pants is going to say that at least the percentage is directional and shifting Matrix glyphs are not. Unfortunately, even that isn't true-- UIs have a long history of multiple sequential progress bars with no indication how many there are in total-- see Office Space. So progress widgets have burned through user trust long ago-- even if I've experienced Windows 10 having a single percentage counter that persists across restarts, perhaps the next update will be the time they break that pattern.

To me there's a big difference between intentionally slowing down the underlying operation (or the ability of the UI to go to the next step anyway) so you can show a longer progress bar, and just having a poorly designed uninformative progress bar on the underlying operation.

Not to you, really? I mean, I guess we can't argue about "how outraged you are", that's up to you.

Do you think those poorly designed progress bars are built to intentionally mislead? It's possible. For what end, do you think? The TurboTax one seems designed to intentionally mislead. Even if they both are, I still prefer one that isn't making me wait artificially longer than the software actually requires though.

People are willing to pay more for meals eaten with heavier silverware

I prefer cutlery that doesn’t easily fall out of my hands when eating though.

This sounds like it would be correct, do you know where I can find a source?

Charles Spence at Oxford University has done a lot of work on this. It turns out just changing the colour of the plate impacts peoples perception of food.

And slower service to boot!

You know what I like for progress bars? The mess that is your average build script.

Tell me how many tasks there are to complete, how many you've done, and some rough details of what you're doing (e.g. is it a network request). Don't be shy about commentary ("This may take a while", "If this fails multiple times do X").

These generally contain all of the information that the developer has access to, and rarely am I left having no idea if something's failed, or what to do if I know it's failed.

Now I'm not suggesting that this is good as-is for non-technical users, but it feels wrong-headed keep iterating on a solution everyone hates (progress bars), rather than trying to adapt a solution that (if other people feel the same as me) is quite well-liked in its domain.

You see a sort of adaptation in some progress bars with the "Show details" button, but that generally sanitised variant, with one line per task and no commentary (and often, for some reason, no task count) feels like it misses all the good parts of what it's emulating.

Strongly agreed.

One tricky thing, though. The few times I saw someone trying to implement the task count, it would sometimes be the case the count couldn't be determined beforehand! So I'd see progress reports like: 1/123 done.... 42/124 done... 45/2616 done... 68/98213 done...

I think scandisk (or whatever the disk scanning utility that runs before Windows boots is called these days) was prone to such ever-growing task counts. I don't know what the right answer here is, except maybe try to split your process into a "planning" part and "execution" part if possible...

Honestly, the example with the incrementing total, while not useful for estimating remaining time, conveys a lot of information. I'd be happy with that for processes that have an unknown number of steps.

> One tricky thing, though. The few times I saw someone trying to implement the task count, it would sometimes be the case the count couldn't be determined beforehand! So I'd see progress reports like: 1/123 done.... 42/124 done... 45/2616 done... 68/98213 done...

SharePoint search does something similar! It doesn't search everything, so it just says "about X items found" based on an estimate. Everytime you click on the next search page, that number gets a little more accurate

This reminds me - GMail does something similar in their search/filtering interface too!

> split your process into a "planning" part and "execution" part if possible

Doing the scanning and the processing at the same time may be faster. It should be clear though when the total has been established and when it isn't yet.

Nix has had a progress indicator for a few years now[0]. It doesn't provide any time estimates but it does show which part of the build it is on (unpack/patch/configure/build/install), how many dependencies it has built or fetched from a binary cache and how many remain. The full build log is accessible with the nix-log command as well, so it's nice from the both a user and dev viewpoint.

For long builds I have stopped watching build logs live altogether and append `; tput bel` to the command to get audible feedback at the end.

For graphical applications, especially on mobile, I wish progress bars got out of the way more. Users ought to be able to continue using an app while a task occurs in a separate thread, and whose progress bar doesn't take up the entire visual field. Many apps, especially on iOS, seem to still be guilty of this.

[0] The creator shows it off here, to applause: https://youtu.be/XVIKScU7Uf4?t=420

CMake has a progress indicator.

ninja has one too.

Progress bars are great when they convey meaningful information... sometimes it's nice to know if you have time to grab a coffee, or actually eat lunch. In my experience (when having to supply said bars) is that they serve primarily to tell the hapless user that things are still happening. In other words, the actual number is not important...what is important is real feedback that things are still happening and it's worth waiting. Or things are b0rked and you should start over. I don't care about a real time or % progress bar...just something that honestly (to OP's point) lets me know that things aren't screwed.

Edit: typos

> In other words, the actual number is not important...what is important is real feedback that things are still happening and it's worth waiting.

And the inverse is that when progress bars are fake, they tell the user that everything is working even when it's not!

I MitM my SSL traffic. This causes Figma to fail to load documents in the most annoying way possible—it shows a progress bar that never stops moving, but becomes increasingly slow as it nears the end. I suspect the bar is programmed to never increase by more than half the remaining distance, or something like that.

After half an hour, I finally realized something had to be wrong, and I tried whitelisting figma.com in my proxy. The document loaded immediately.

If Figma hadn't lied to me with a fake progress bar, it would have saved so much time...

I've gotten real good at recognizing those kinds of progress bars; I think Window Explorer's search had one and it trained me to never trust them.

I recently found out that you can prepend your search with "name:" and windows search will only match against filenames which is the behavior most users expect by default and much faster than whatever nonsense windows explorer search normally does. Example:


Windows Explorer, IIRC (I don't use Windows anymore), searches the content and title of most(?) files.

It's not just search when the progress bar appears, though. Also when trying to enumerate contents of a folder - e.g. when you're accessing a networked resource, or one that may not be viewable with your privileges. You then get this bullshit progress bar that speeds through the first 3/4, and asymptotically approaches 100%.

VSCode has a progress bar (well a throbber) that shows up when the language server has waited long enough that the UI should show some activity. But for my workflows it only shows up when something has gone wrong. So when I see it, it’s a good indicator to either restart TS server or reload the whole window. Not a great experience or solution!

> I don't care about a real time or % progress bar...just something that honestly (to OP's point) let's me know that things aren't screwed.

That's where "marquee" progress bars fit in. Those poor abominations that, like Sisyphus, progress without advancing, because a simple activity indicator wasn't user-friendly enough.

Especially fun in Web UIs where the callback that would remove the spinner will never be called because some error occurred somewhere in between and is only logged in the console where no normal user will ever see it ...

Personally I feel that to be very much a subversion of the »things are still moving, so stuff is still happening« assumption that has been common in normal desktop applications.

Maybe spinners like these need a kind of "dead man's switch", where something needs to keep telling them "yep, still working" every so often, otherwise an error is shown?

Many APIs don't have that - for example with most IO operations you get a return value when complete or an exception on failure, and that's it.

Getting something like a callback for progress would require modifications all the way down the stack, akin to what's needed for fully async code.

Then the `try { ... } catch { heartbeat() }` pattern will emerge.

Which is a sane pattern if a language has proper destructors (a seemingly non-existent thing in GC-enabled languages, unfortunately).

In C++, you'd stack-allocate an object representing a spinner, that spawns said spinner in its constructor, and deletes it in its destructor. Then the spinner doesn't outlive the processing code, no matter what path execution took to end the processing.

There are similar patterns in GC-enabled languages ("with" idiom). Async does throw a wrench into this a bit, though.

That’s a different pattern than I was trying to illustrate. I was demonstrating unsafely catching/ignoring/hiding errors and asserting health when it’s demonstrably not true

The app I work on is plagued with this issue. I just wish I was given the time to go around and fix it everywhere.

As with so many of the issues in web apps, its not even complex or hard to fix these issues. Its just no one cares enough to schedule time for it.

You are a hero. And to the extent you’re unsung, I will sing your praises.

My ideal spinner would be a decreasing arch, telling the user how much time remains until their request timeouts and fails. Uses the same space as a spinner, but conveys more information.

> Especially fun in Web UIs where the callback that would remove the spinner will never be called because some error occurred somewhere in between and is only logged in the console where no normal user will ever see it ...

I know it’s unpopular in these parts but checked exceptions would make this impossible.

> the actual number is not important...what is important is real feedback that things are still happening

Absolutely agree, but then, don't make it a percentage progress bar. Make it one of those "amount unknown" bars, or better yet, a spinner or game-like loading screen. Something with movement that tells me things are happening. Don't pretend to know "how done" it is if you don't know.

The web has ruined those feedback widgets for me. Now every time I see one of those spinners I think “oh look, a gif that will keep spinning even if the process I’m waiting on has failed”.

That is a good point and rather unfortunate...

Lying progress bars are one of those ubiquitous anti-features which make me suspect the people who write the apps that have it or who decide what features they are to have never actually use their own software, or they'd realize in a heartbeat how incredibly annoying and frustrating lying progress bars are.

I'd love to hear an HN reader who is brave enough to own up to implementing one of these explain the rationale behind them.

Well... story time. I had to implement a lying progress bar at the behest of my client. We could not reliably predict much...network speed, file size, moon phases, sock colour, etc would change things all the time. The client wanted to show the customer that "things were happening"... so we made the bar always move. The logic was that once it hit 90% or more, customers seemed to be invested and would wait forever. And yes, we tracked the abandonment percentage against progress bar percentage.

What's wrong with using something like a spinner in that case though? The big issue with a lying progress bar is that it not only lies when things are happening, it also lies when things are broken, possibly wasting a lot of your users' time.

The goal isn't to save the user time. It's to maximize user conversion rate.

You mean abandonment? Most progress bars are shown when I'm already using your application.

Our most important users (read: $$$) were also the most sophisticated. They also appeared to like numbers... as numbers helped them when they complained back to us that our system sucked. If we took information (as bullshitty as it was) away, they accused us of hiding the truth. As Calvin said to the monsters under his bed... they lie, I lie. Our process was very heavily weighted near the end...so if you made it to 90%...and hung on, it would very likely finish. Again, you need to know your users and play to their strengths/weaknesses and track metrics.

1.) User submits ticket stating "action X is slow"

2.) Project Manager creates dev task "make action X fast"

3.) Too much work to actually make action X fast. Decides to make the user feel like it's going faster.

4.) Deploys fake progress bar to prod. No new tickets.

Its incredible how much faster you can make an app feel by just making the UI respond faster and filling in the data later. As long as something happens instantly its satisfying.

Is this the idea behind that? I can't think of anything I hate more than a web page that loads with absolutely nothing useful, then waits for all the JS to load, then loads content.

I suppose I understand wanting SOMETHING to show up, but could we PLEASE make it be the raw text first?

People love to see progress rather than start to finish speed. Its why getting stuck in traffic is frustrating while riding a bike is not even if you take longer overall.

A blank page for 2 seconds is worse for the average user than a UI template instantly and 2.2 seconds of content filling.

This is why there’s an ever evolving art of progressive/lazy image rendering. There are several techniques that involve populating a blurry or even polygonal version of an image that eventually resolves to the real image. The ultimate payload is larger, and the time to render is greater, but faster UX gratification is more satisfying.

This reminds me of a counterpoint to my top-level comment of how frustrating Apple’s progress bars are: way back in the early OS X days, they did user tests that showed people respond better to longer running progress disclosure than shorter running real progress. So they literally baked a delay into the OS X boot process that would make booting take longer but show a more predictable progress bar.

I've implemented quite a few lying progress bars.

It's impossible to estimate total completion percentage when one part of the operation is CPU-bound, and another part is disk-bound.

(I haven't had to deal with network-bound operations, but I feel for those who do.)

Truth is probably possible, but more work than it's worth, when one part of the operation is O(n) and another part is O(m^2).

If the feature is a week late, it doesn't crash, the answers are right, and the operation completes in a reasonable amount of time, I'm moving on with my life.

Completion percentage doesn't have to be measured in time. If you've completed the CPU-bound operations and are just starting disk-bound operations, it's totally fair to say "50% complete", even if you expect one to take much longer than the other.

Alternatively you could use multiple bars - one showing the number of distinct tasks to complete, and the other showing the estimated time progression of the current task. Ideally chuck an expandible debug log underneath it. You probably want to be implementing a debug log while developing to test the thing anyway, just leave it in there! A lot of installers use this kind of progress bar and I've always found them to be the most user-friendly.

Made one for an internal feature using an overly simple algorithm (% of tasks completed). I was the only one using the tool so I understood the tradeoffs of the progress bar. After a while this tool made it into wider use, but the progress bar remained.

Such a bar is fine imo, especially considering the ratio of effort to return, and much preferable to a spinner. Even if the relative size of various tasks is totally random and disproportionate, at least when the bar fills up, even a pixel, you know forward progress is still being made. The spinner will just spin forever, whether it is deadlocked or not.

Conveying progress in a lot of cases is difficult. Sometimes you have two sets of tasks where the first set determines how much is done in the second. That means you can't accurately predict the overall length of time required to finish everything.

You could split up the overall progress into two parts, 50% of the bar each. The first part might take a while to finish and when you get to 50% you determine how much is left in the second half, and if it's quick, you immediately jump to 100%. On the other hand, if the second half takes really long, now you're sitting there waiting what seems like an eternity to do the second half.

With some clever design, you could have a smarter progress bar system where each task is weighted and adding it to the overall progress re-computes how long everything is, but now you have a scenario where the progress bar could shrink as you get more accurate about the work ahead.

If the time to complete a task is short enough, a lot of these tricks for more accuracy just aren't worth it, and often require fundamentally changing the architecture of your underlying processes, making it more work than it's worth. Hence, you end up with funny things like finishing at 75%. Though, to be fair, they should at least jump to 100% before finishing. I think that's a common bug that comes up, not letting the full bar show first before dismissing.

I wrote a progress bar for an app where it wait time ranges from 5 to 20 seconds, 20-80th percentile for each different function had a range of like 8 seconds--it doing fancy stuff with Selenium. :)

I mocked it up in Figma, I didn't display any numbers, only a cute lil line. Then built it with React Native, super easy and quick, it looked & felt great to me.

So for the actual estimate, what I did was store how long it took to run the task for my users, and then select the 95th percentile from actual runs to get an estimate. Then when they loaded the app, I would send over the estimates (along with their account info and what not). I figured if it ended sooner than what it was projecting, the user would be happy, or at least I was.

I used my own app, and kept tweaking it until it felt right, and it felt really good. YMMV chef's kiss

I suspect fake progress bars do pretty well in a/b testing for page abandons, versus nothing at all. Especially if they show more "done" than not. I don't like it myself, but perhaps it's comforting to those that don't know better.

Can confirm, they work great for users. We had a system where some old things were traditional POST+redirect and the rest was all React with progress bars, disabling buttons when submitting, etc. Users demanded we make everything use progress bars because it's "faster". Our p95 DOM render was 400ms so it wasn't "slow" to begin with. I'm confident it really was the progress bar.

> Our p95 DOM render was 400ms so it wasn't "slow" to begin with.

Not sure why exactly you put quotation marks there, but 400ms is incredibly slow, at least relative to human perception and what computers should be able to do. Consider what AAA games can render in 16ms.

Would love to see a web app you've built that does a HTTPS GET round-trip plus browser render in 16ms.

I didn’t implement one but a former employer did, and [consults my exit agreement] the only thing I can say is they got complaints about long running processes that depended on third party data sources that were so unpredictable that having a colored bar gradually fill up a colorless bar made people stop calling so much, even if it didn’t convey much information.

I made one of these.

We needed a progress bar, but there was no way to estimate progress.

When progress bars are not useful it is because the underlying problem is hard to extrapolate faithfully. If you are doing just a few tasks where each one takes a significant different time to execute, it will be hard to estimate. More often than not, they work fine, IMO. When they don't, it is because for that particular problem it is genuinely hard to do. It isn't programmer's laziness, I think, in most cases.

Most users don't understand that making an accurate progress bar is incredibly hard, for most tasks. Is not very intuitive, but once you start looking in to it you realize that almost nothing in a computer is deterministic. Task switching, cashes, file system buffers, disk fragmentation, variable clock frequencies, and loads of other factors, make the speed of a computer very hard to estimate.

I do favor progress bars that say things like "you have downloaded 47% of file X", because its a statement of fact, not an estimation of future performance.

Progress Bars are the most user visible insight into The Halting Problem that our entire industry has. In so many cases, if we knew exactly how long things would take to compute we'd have already computed them or we'd have a world bending solution to The Halting Problem that would change everything. It's really hard to describe NP Complete/NP Hard to the average user, and it shouldn't be a surprise that the poor tool that keeps having to do it over and over again in so many places and ways, the lowly progress bar, keeps getting blamed for our industry having failed to solve (and unlikely to ever solve) The Halting Problem.

I often see the suggestion to display spin animations instead since estimation is often incredibly difficult if not impossible. I prefer progress bars because even if they aren't accurate, the relative directional growth shows me that something is actually executing. With a spin animation, for all I know, somethings caught in a loop.

This seems a little funny to me, since the purpose of the spinner is so that you know the computer isn't caught in a loop — it's "busy". It's true, though, that the computer could still be stuck even though it updates the spinner. This is a hard problem to solve.

Abusing progress bars are not a good response to this, though. I would rather trust progress bars for what they are meant to show rather than as an indication of true activity. After all, you still can't tell whether the progress bar kept moving, but the process is stuck in a loop.

>This seems a little funny to me, since the purpose of the spinner is so that you know the computer isn't caught in a loop — it's "busy". It's true, though, that the computer could still be stuck even though it updates the spinner. This is a hard problem to solve.

The problem that people might assume the computer is stuck in a loop or at any rate that the animation is not going to stop is related to spinner animations on websites. Since the spinner is not a function of the browser, but is instead something implemented in the individual site's code, then stopping the spinner needs to be also coded for and many sites neglect to write the code for "when error happens stop spinner and tell them that things went wrong".

So over time people exposed to negligent website spinners start to suspect any spinner that takes too long.

That's because spinners used to show that the main thread was still responsive, but these days are used in different contexts where this isn't really something that it applies to anymore.

right, I guess that says it more succinctly.

In the old days of 68K Mac, it could be even worse. The spinning hourglass was often animated during a timer interrupt, while the main application might have died altogether.

A progress bar should not indicate progress over multiple tasks — a segmented progress bar is better, or a series of spinners, or just a single spinner for the whole set. A progress bar should measure exactly one metric, where the total is known.

It reminds me of the old (maybe it still does it, I dunno) windows install progress bars vs ones where multiple things are wrapped into one.

With multiple things wrapped into one, you often end up in situations where 0-99% (or whatever) might happen super fast but that last 1% takes ages, making the progress bar useless as a "something's happening" indicator.

Those old windows installers used two bars: the top one was basically a steps indicator (file N of M, for example) -- just like the single bar for multiple tasks. But the second bar was a per-file bar. So if step 99 took longer, you had a second bar showing you that steps/files progress.

I played with the idea of using a singular circular progress bar for composite progress notification. The basic idea was that if you keep the tail chasing the head, and the head always moving clockwise, the progress bar never gives the impression that it "shrinks backwards", it is always forward motion, but in the worst case when the tail catches up with the head (you discover more sub-tasks) it basically becomes a spinner until the tail starts to lag the head again. Tuning the animation parameters for that provided a lot of options to get a good feeling progress bar that reported a heterogeneous source of various tasks, some of which discovered/added while in progress of the overall whole.

My demo has unfortunately fallen to web bit rot and needs to be updated, but the code is here to explore: https://github.com/worldmaker/compradprog

Yeah, I think I remember those! If it were me, I would turn the segmented bar into a checklist, since you can add a description and I think it looks nicer. But the approach was a good one imo.

Sure, that top bar is a "steps completed" bar, so something other than a normal progress bar may be better. A checklist would work, unless space confined. Depends on the number of items. Maybe a segmented bar where it fills one segment for each item. If there are a lot of items, though, just an "X/Y steps completed" may work best: its simple and easy to understand.

Back in Windows 3.11 days, I noticed a patter with installers. Their progress bar would go steadily up for quite a while, and then suddenly spend 3x as long on just one or two percentage points.

It didn't take me long to realize that the progress bar measured bytes written to disk, but when it was seemingly "stuck", it was creating a lot of small files.

Instead of bytes written, what I really cared about is "how done are you?" and that would have been better represented by a function of both number of files created _and_ bytes written. I don't think the weighting of those two had to be very accurate to be a big improvement.

Exactly! The biggest problem with most progress bars is that they tie together multiple unrelated things that aren't even measured in the same way to a single indicator.

If there are multiple independent tasks, give me multiple independent indicators of their state. Multiple instances of the same class of task can of course be grouped, you don't need to list every file copy independently, but a file copy and an external dependency installer shouldn't be two stops on the same progress bar.

It would be nice if they were accurate, but with my limited experience making them, I don't expect them to be. I've actually had the fact they are there screw up rendering.

Whatever Apple is doing for iOS and MacOS updates isn’t cutting it...

The problem with progress bars is us. We expect different behavior and the most population has wrong idea about how systems work. While an average Joe likes pulsing bars that advance regardless, other people hate it, because with time (years of experience) it obviously feels bogus.

Best (honest) progress bars are still those of software package managers, because they simply update on a percentage, have no step/idle animations and always show where you are exactly.

Surprisingly, MS has recently done a great job with explorer's copy progress by showing a graph. Filesystems and disks have nonlinear performance and rather than trying to extrapolate, they allow you to see when caches exhaust and the speed falls to its final value. When it stops or starts to degrade, you see that too and may try to pause a competing/interfering process.

I have only implemented progressbars on the web.

After various progressbars on different projects my approach is this:

- Have an array of tasks

- Have a % progressbar

- Each task adds (100/total_tasks)% once completed regardless of how fast it is

Now comes the fun part. There is this single task that takes up the majority of the time amd your progressbar is stuck at 56% percent for too much time compared to the other tasks. You don't have feedback as a user. Is it stuck? Is it still going on?

Now is the time to optimize for use experience!

Why is this task taking so long? Are you loading a huge asset? Break it up, compress it, optimoze it. Are you doing something CPU intensive? Break up your computation over distinct tasks.

This attitude has led me to implement better technological solutions as well as user experiences

Good on you. Most progress bars are about user experience and not so much about accuracy. People just want to know that there's a long sequence of work and that progress is being made.

It's often an illusion and showing too much how the sausage is made makes the user start asking questions about what's happening behind the scenes.

That said, a long task that is prone to failure due to external factors should definitely be conveyed in the progress bar. If a bad network connection is affecting a process from finishing, you obviously want the user to know that so they don't blame the software for being slow. :)

I've found in apple world progress bars seem to lie more ( not that others don't). Worst of all are the progress bars that take forever to get to the end, then, start a new progress bar. Multiple phases with multiple progress bars is pure evil!

I think duty #1 of a progress bar is just to reliably communicate whether it is frozen or not. In many cases, slow progress is fine as long as it isn't stuck.

Yeah, the main thing I want to know is that the process is still working as expected and not crashed or interrupted. In many cases that's more important than the time value.

The problem with progress bars is that they're ambiguous on many levels.

What does the progress mean? Is it the fraction of work done or an indication of time left?

Progress bars don't necessarily lie - they simply omit useful information. Estimating progress is hard if there's variables involved that are outside the application's control, e.g. network speed or task switches initiated by the OS.

Task-based progress bars suffer from being "jumpy" and terribly inconsistent, because some tasks take longer than others and the progress indication doesn't allow to estimate the remaining the time.

Time-based progress bars are bad, because they are dynamic by nature of factors mentioned earlier, so ETA might suddenly jump from 1:23 min to 58:07 min or just as bad from 15 minutes to 3 seconds.

This is also the reason why "this is how long it took for other users" is not a great solution either: if your particular circumstances (network speed, server load, ...) are vastly different at the time, this would solve nothing and result in the same complaints.

Progress bars are just an estimation and a mixture of tasks left, ETA and a generic activity indicator ("the app didn't crash and still makes progress") might be more informative.

EDIT: for short tasks (e.g. 20 seconds or less), a simple progression of messages like "working on it", "just a moment", "almost there", "finished" might be the best option.

A progress bar is a chart, nothing more, nothing less. And as any data scientist will tell you, charts without labels are bad charts.

A progress bar should measure exactly one dimension, where a total is known, and a label should show what the dimension is. Usually progress bars implicitly measure "time left", but the total isn't known in that case, so progress bars are inapproprate.

For most "loading" scenarios, a spinner is a more appropriate element.

> Usually progress bars implicitly measure "time left", but the total isn't known in that case, so progress bars are inapproprate.

Are you sure about that? I'd argue that most progress bars explicitly measure tasks/work left and it's the user who wrongly correlates this with "time left" in many cases.

Note that the OP didn't complain about time, but about the percentage not going from 0% to 100% for example.

Yeah, you might be right about that. Still, that's not using a progress bar correctly if it's measuring multiple tasks — they should be measured individually, with spinners or a segmented progress bar.

Many progress bars are implicitly segmented; it's just that segments are determined by the programmer and never exposed to the user.

Progress bars are just a tool that needs the right material to work on. I realized that when i tried to progress bar-ify a recursive task.

I think it's more sensible to find a UI language that can seamlessly incorporate a progress bar and a dumb spinner with some note on what's going on. Which one is shown/used will depend on the task that is being loaded. Different words for different things.

These progress bars lie because they don't represent what the user thinks - either intentionally or from poor UI design.

I like MS Windows 10 "file transfer over a network" progress bar (though the pause button seems iffy...). The "hopes and dreams" simple progress bar is labelled factually and can't be accused of lying. And more information is available upon request and is simply factual.

A lot of work for a simple case of transferring files though. Much easier to default to the boring progress bar and some 0% to 100% assumptions to abstract things away so the "dumb user" doesn't have to worry... (NOTE: I hate the seemingly persistent concept of "dumb user" that so many people have.)

If your users have worries about your application performance to the extent that you are required to address them, then 90% of the time a dumb progress bar isn't the full answer. It may be an answer that makes management or user testing groups happy, but perpetuates the lie the article addresses.

Edit: snipped crap and added caveat note.

A long long time ago, I was testing a web site. I accidentally suspended the server. Mozilla's progress bar stopped right there while internet explorer kept going, progressively slower, until the browser threw an error around 98%. Also, let's not forget windows file download/copy estimations. Lying progress bars are at least as old as windows.

The windows file copy process bar wasn't lying though, it gave you an honest estimate but was just really naive.

Progress bars work best when they are analyzing repetitive tasks analyzed either in series or in parallel without overhead. If I'm doing something 10,000 times, and if there's no overhead on parallelization or finishing steps. I can be reasonably certain that after 7,000 times, 70% of the time has passed and 30% remains. Maybe there's some step by step variability, but chances are it's dominated by the fraction of iterations complete.

Progress bars work worst when they are combining extremely disparate steps. You might need to run 10 functions, but if one takes 0.1 seconds and one takes 45 seconds, it makes little sense for each step to be counted the same atomically or to present each as 10% of a progress bar.

The absolute worst case scenario is when you depend on an external resource about which availability is unknown but highly variable.

When it comes to progress bars that lie, I think of two major examples:

1) Apple software updates or OS installs usually never have the bar progress past 30% or so. I don't think they lie, so much as 100% is actually at 40%.

2) Windows installation. Copying Windows files jumps straight to 100%, Expanding Windows files is the only one that provides meaningful indication, installing features and installing updates happen instantly.

Then, it goes into a period of indeterminate loading spinner after a reboot.

These days, where possible (i.e. on VM, or if I'm in the OS already) I just use iStat menus or other monitoring software to check if things are using the processor by checking the CPU usage, CPU power consumption, disk read/write, and network activity. If something's happening, I let it sit. If not, the process needs to be restarted.

Progress Bars I Have Loved:

* Tells people what stage we're on. "Downloading", "Installing", "Cleaning Up".

* Can make bar for each step or guesstimated across all steps, either is ok.

* Do not show sub-step time estimates. If you show time estimates at all, do it for the whole process.

* Bar represents definite knowable progress: files moved, MB downloaded, etc. It thus never moves backward. If the stage has nothing knowable, make the bar full-width and stripey as a spinner equivalent.

* Able to open a verbose view that shows log stuff: actual numbers and filenames. The MacOS installer has this and good lord it was important when the MacTeX bug hit

Does this surface information that unempowered users don't need? Sure. Their eyes will just glaze over and it'll be fine.

Reminds me of a prank I pulled years ago. The company I worked for had some sort of enterprise encryption on the laptop on the hard drives. A friend had some reason to decrypt his to resolve an issue. Progress was very slow on a large progress bar and hard to determine actual progress as the estimated time was over 8 hours so he put a post it to mark the progress and would check intermittently. I spent the day moving the post it and he was convinced it was progressing, pretty sure it never finished. I guess the lesson is maybe progress bars should state a percentage as well.

Author here. Anyone have thoughts on my data-driven approach described as Solution #2?

Basically: tell me how long it took other people.

It depends on how large the variance is, which I suppose you could measure first. You could even show the existing distribution (or typical range) within the progress bar.

A somewhat related approach is used by build servers showing a progress bar of the current build base on how long the previous build(s) of the same project took.

That would work quite well for low-volatility tasks. iOS upgrades is a pretty good example, for one. In PC-land it gets a bit more difficult due to variations in hardware; see video games.

In my opinion, it's not worth the telemetry.

Aren't they tracking every app launch? Data on update times would be a drop in the bucket.

A humble request: please don't make spinners (GIFs, CSS animations, whatever) visible in the initial response HTML of a page, if they're meant to indicate some sort of AJAX loading. Lots of sites do this, but it's unfortunately too robust. The spinner will appear, and run forever, even if:

- We forgot to embed the JS that does the AJAX loading

- The JS has an error before it even makes a request

- The src URL of a script doesn't exist

- Some cross-domain issue prevents a script loading

- The user agent doesn't support JS

I accept that it can be tricky to remove a spinner correctly in the face of certain error conditions, but it's trivial to avoid showing it until it's meaningful. So please: only insert/reveal spinners programatically, just before the associated request is made.

In fact, this same logic applies to all UI elements that are only meaningful thanks to JS (e.g. buttons that require an event handler, rather than submitting a form); such things should be inserted/revealed programatically using JS, not visible in the initial response HTML, so we don't end up clicking over and over on a button that's useless, etc.

I get that many Web devs these days don't care about progressive enhancement, and like to assume all users have HTML5+CSS+JS+etc. but even that assumption doesn't excuse spinners that lie when a connection fails, or a server is misconfigured, or a third-party moves some assets, etc.

Here's a "watermelon" bar—just need to collect the first tick on each job and then the last recorded tick or tick on complete. Then you can show a nice visualization that shows the current time and distribution of expecting wait times.


And you could break it down recursively by task as well.

A progress bar is only appropriate to show one metric changing between two known points over time.

- A progress bar should not measure multiple tasks, unless each task is of the same type (e.g. converting a batch of files, _not_ system booting)

- A progress bar should not measure "time left" unless it is literally tied to the value of a timer (i.e. _not_ "time left to download big file")

- A progress bar does not show "busy state" — a spinner does that. A progress bar can stop if e.g. it measures bytes of a file downloaded and the network connection drops; a spinner will still spin.

- A progress bar should include a label to explicitly state what it is measuring (otherwise users will assume it means "time left")

People like to see progress bars because they want to know "progress is being made", but a progress bar is not always appropriate, depending on the situation. Instead, consider using:

- Spinners show activity is happening. Use when there isn't a single metric to report, or the "bounds" of the metric aren't known.

- A checklist can show different tasks completed in sequence. Can be combined with a spinner on the "current" task

- A segmented progress bar can replace a checklist when each task could be represented by a progress bar

Just my opinions, I guess, and obviously we don't live in the world where the above is applied, but it feels good to have it sorted in my own head. Curious what others think of this scheme.

Oh come on man... Get Real!

Next you'll be asking programmers to estimate how long they going to take to do something...!


I made a mobile progress bar tool that pings your phone when your code is e.g.


-80% done

-if the CPU for a given process drops below 10%

The CPU tool works for Mac OS installers and anything else. Works decently on Linux too. I call my tool SpookyLoop:

The article teases at the indeterminism of ops on different computers, and also the halting problem at the theoretical level. But an exact estimate isn’t a necessary experience. I contend that the ultimate UX is going for a walk and doing something else afc with some confidence that you’ll be ping’ed when it’s time to return. Beyond that, predicting time-to-complete becomes an opportunity to create trust in a brand. I’d much prefer a text message when the install is done than checking my TeamViewer every few minutes while on the go. If a software can provide that, I’d value that more than a data driven estimate that still might be wildly off

My suggestion is: Display a plain number (rather than a percentage); but only display the percentage if the total required is actually known too. For example, if you need to download a two gigabyte file, and the file size is already known, then it can calculate the percentage, but if the file size is not known, then it should only display the total number of bytes downloaded.

This is separate from time estimations, though. The progress may not run at a uniform speed, which is OK; just mention the percentage of progress if known, or a plain number if not. If there are multiple steps, display the progress for each individual step, and document what the steps are.

In a few cases (e.g. hashcash), the progress is not known, so just a "spinning" indicator (or displaying a plain (non-percentage) number which just increases while it is executing) might be used instead.

I think I'd rather just have predetermined steps/milestones. Think about it...what does 71 percent really mean? Would you get excited when it goes it 72? It's just an opaque, useless metric.

If instead I can see something like...step 1/5, downloading package... that's far more meaningful, at least to me.

72 means it wasn't stuck on 71 and something is still happening.

I agree in that there should be text with the progress bar showing what the progress bar actually measures, e.g. “57 of 285 records processed” or “3:05 (ETA 10:34)”. If you can’t, then it’s a sign that a progress bar is probably not appropriate.

I also have seen Apple progress bars rigged to 75%, for some unknown reason, but my biggest offender is my DVR phone app.

On connection it shows the last image sent by the camera, and a progress percent. The progress is really a connection timeout, and you can't be sure it connected or not until it reaches 98% and fails.

So, the problem with progress bars is that they are rarely accurate, and the problem with static "processing..." messages is that it's imposible to tell if the app is frozen.

How about an indeterminate progress bar, but it has a button you can click that tells you the app hasn't died? :)

I'd thought of making a progress bar library that you'd configure with information like:

- author_uuid: 0xdeadbeef

- download_size: 10GB, domain: example.com

- file_write_size: 10GB

- cpu_time_estimate: 8s

- download_size: 100MB, domain: othersite.com

- file_write_size: 200MB # after decompression

- cpu_time_estimate: 30s

and let it learn over time. My computer can figure out how fast it can download from example.com based on previous transfers. It can figure out how fast my hard drive is based on previous writes. It can figure out how fast its CPU compared to that particular vendor's test system based on previous runs. And if a company like Apple were to deploy this, they could pre-populate the database with very accurate guesses for file write speeds and CPU seconds.

If you had that information, the progress bar could have a pretty solid idea of how long the total progress would take.

That would depend on the APIs and language you use, of course; some of them might do buffering or copying differently.

If you're making games targeting consoles there are usability requirements. Any loading screen which takes more than a few moments needs at least a spinner to indicate it's not stuck and if it may take more than a certain time (30s? 1 min?) you are specifically required to use a progress bar. But there's no requirement on how accurate it is.

While working on a popular AAA franchise at EA, we had loading screens which were sometimes really long and depended mainly on your connection speed. We estimated a worst case time for clients with slow Internet but not slow enough to time out and then made the progress bar driven by a timer from zero to this time.

Even knowing how it worked I repeatedly found myself intently staring at the loading bar.

Wouldn’t accurate progress bars solve the unsolvable halting problem?[0]

[0]: https://en.m.wikipedia.org/wiki/Halting_problem

I mean yes, a universally accurate progress bar would be impossible, but that’s vastly different from a mostly-accurate application-specific progress bar. The point of the article is that most software barely even tries to give you something reasonable.

Not only do they lie, but they are often poorly implemented. I was pairing with a coworker, and a download was taking forever despite his fast speed tests. (I think this was chocolatey) and we tried again after 15 minutes of waiting with `--no-progress` and the download finished in seconds.

We joked that it must take a lot of work computing those VT-100 characters and went back about our business, and I swear to god, an hour later the exact same thing happened in a completely different piece of software.

I can't believe the art of software development has regressed so much in my lifetime.

> Every time I upload a lecture video to YouTube, it goes back-and-forth from "0% processed" and "100% processed", repeatedly, until it is actually done. I've never seen it say any other number.

I’m uploading a couple of 50–100m videos each week, and a lot of the time it stops off briefly at 95%, 99% or both before reaching 100%. (Also, “100% processed” comes before “finished processing” or “SD processed, processing HD”.) I’ve never seen it go back down, only ever upwards.

(Huh, today in uploading a video I glanced at it after a while, and: 83%… 84%… 85%… 86%… meaningful percentages and time estimates. Maybe they’ve fixed this, or at least improved it?)

are there any good composable programming abstractions for expressing progress in a system?

as an analogy, I really like RAII-based cancellation for futures in rust. dropping a future means the caller is no longer interested, and the sane behavior of cancelling all of the subfutures is the default. this seems simple at first, but dropping a single future may end up cancelling operations on other threads, freeing buffers, and so on, and the programmer profitably stumbles into the correct behavior.

so, it'd be nice for having a similarly composable abstraction for reporting progress in an asynchronous system. `Control.Monad.Progress`[1] just uses a float in [0, 1] to represent progress, and `NSProgress`[2] has a bit more going on but still requires the programmer to manually partition a parent task into its subtasks.

I'm not sure this is altogether possible, but I could imagine 1) a library for expressing the ground truth of where parts of a system are and then 2) a heuristic based layer above for turning snapshots of the system into time estimates and percentages working well.

[1] https://hackage.haskell.org/package/progress-reporting-1.0.0...

[2] https://developer.apple.com/documentation/foundation/progres...

Most progress is determined by a multitude of factors, network speed, device speed, RAM size etc... And even some things that are unknown to the process; server load, problem complexity, problem size...etc. It's just easier to lie!

A good solution is to have a progress bar that goes for a certain amount of time 0->10 seconds. But if it finishes earlier, then it quickly jumps to 100%.

Still a lie, but it's satisfying to watch and accurately finishes every time (so it's harder to spot the lie).

Here is a universal progress bar in pure CSS (no need for any annoying JS code that needs to know what is actually going on), similar to the old lying IE bar:

    .progress {
      height: 100px;
      background-color: red;
      animation-name: example;
      animation-duration: 10000s;

    @keyframes example {
      0% {width: 0%;}
      0.1% {width: 50%;}
      2% {width: 90%;}
      100% {width: 99%;}

I don't see a problem here that needs solving as bad as the article suggests.

It's comforting to see something is happening and things are moving forward.

I just don’t think it matters enough to warrant the effort. Say you do architect the system capable of rendering the perfect loading bar, because it just has to be a systemic solution... what did we really solve here? It still takes 10 seconds to do the operation, there is just better incremental progress? Decent incremental progress is basically the same as perfect incremental progress IMO

This is the one place where dark patterns would come in handy.

During the task, hook me up in another thread with a ML chat buddy that baits me with political statements chosen to maximize my outrage. Since my attention has been fully captured for the duration-- regardless of the length-- the programmer doesn't have to waste any time trying to measure how long the task takes to complete.

For short activities (less than a few minutes) I don't need the progress bar to be useful, I need it to be reassuring.

Any longer than that, reassurance comes from visual previews of what's happening, see vray preview windows for renders. Basically that feeling of shit getting done from watching laser and 3D printers do their thing.

I'm going to be a radical and say it really doesn't matter any more. We've just gotten used to them not being accurate.

If your progress bar implementation is getting things wrong, you can probably just replace it with a loading spinner and call it a day. That's a vastly easier solution than making the progress bar accurate.

Disagree with the gist of the post. Completing after 75% doesn't mean completing after 75%. It means the developers had to estimate the time taken for 2 subtasks (e.g. uploading and committing via an API request) and said that uploading was likely 75% and the commit step 25%. What happens is likely that the final 25% was so fast it seemed instant.

The options are: 1) don't show progress. Show a marquee, as to not lie. This is terrible. Please don't do this. 2) Show two phases. E.g. the first phase progress runs slowly from 0-100 and the second one runs instantly from 0-100. 3) Guess better. Such as do it adaptively. The expected time for phase N is estimated from data (e.g. last time for commit phase, or from a bandwidth estimate from last upload times the file size). 5) Add a minimum phase time so that instantaneous completion takes e.g. 50ms, so people get time to see the completion at 100%. 4) Do nothing. No one expects progress bars to run linearly.

There are so many good options that are better than "don't show progress, only show activity". Even the do nothing/status quo alternative is much better than no progress bar.

Imagine if you used the example with YouTube uploads in the context of giving project progress updates to your boss: " day 1: We're at 10% completion; day 2: we're at 20% completion; ... day 10: we're 100% done, deploying tomorrow; day 11: actually we have to start over from scratch..."

>And yet, every single photo and video that I export from Dropbox finishes at 75%, regardless of how big the file is.

What does he expect? That larger files go over 100%? Who knows how the progress bar is calculating, but the assumption that every file shouldn't finish at the same percentage just seems very odd.

I think you misunderstood - they finish at exactly 75%, which means it should be easy to make them all finish at 100% as they should.

There's an obvious explanation for why they finish at 75% though - to export a photo it presumably has to download it, and then do "something else" (maybe format conversion?). Measuring download progress is easy, but presumably the "something else" was more difficult to measure the progress on. Most libraries don't give progress feedback for most operations.

So the developer just thought "screw it, we'll allow 25% of the time for that processing". Based on the video they were wildly off but accurate progress bars are really low priority for a reason.

Ha. Reminds me of the use of mirrors in elevators, basically they give us gullible humans something to do while the machine wastes our time.


So what does a perfect progress bar would look?

Will it able to predict if my internet connection going up or down in next few seconds of starting a new download.

I think the current progress bar represent the task progress not the estimated time left and the author is looking for something that shows actual time left.

It isn’t always straightforward what 0-100 means - if you are downloading a file then that is one thing but what if you need to call an api, fetch some data, process some data, call another api - what percentage is each section or api call?

Users just want to know it is working.

100/n(API calls)

Users understand that 0-20 might take longer than 20-40

With Internet cut off, Netflix slowly moves the progress bar to 25%, waits a long time, and gives up.

We have a kettle at work that shows a two-digit temperature in celcius (100=boiling). When you ask it to bring 94+ degree water to 100, it slowly changes the number from 94 to 100 without turning the element on.

Clearly enough people prefer to be lied to.

Where will it end...

What I hate the worst is a spinner that means nothing. I lose my shit when people do this at work. It's so easy to do a simple percentage based progress bar, I don't know why it's not everywhere.

Don't get me started on the progress bar of Apple's Time-machine ...

I remember a Windows 95 progress bar telling me that a file copy would take quite a while. From memory, something like 10^10 seconds. For a few MB.

The Novell client used to finish installing at about 103%

Apple seems to be worst at it. Try backing up your videos on iCloud and you can forget ever being able to watch them again...

Yeah. Also, the Cancel button often doesn’t.

the second suggestion where they estimate the time to completion in a matter of comparing the time other uses had to wait. They could test it out on a specific scale and that's practically it. You don't need to do anything difficult, just log the time it takes and then show the average.

They don't lie. They are simply an everyday manifestation of Heisenberg's Uncertainty Principle.

Progress bars are way better then spinners: They communicate an time/duration estimate, at least. Even in the case it is bad, this is always better then just showing a spinner, indicating that some system is doing something. Spinners got omnipresent since the Web 2.0. Nowadays for me they are almost always a sign of lazy programmers with an "that's good enough" paradigm.

Progress bars that lie are seldom better than spinners. I suppose what is needed is an informed spinner. It would have to be visually different than a bog-standard spinner. I have seen many cases where the numbers on the bar were entirely made up...but they seem to keep people happy. The illusion of progress maybe?

sure, but even the wrong numbers can be useful because they provide some information.

like the "75% max" example from the post. Does it lie? yes. Can it be useful? very much, it is pretty easy to compensate.

I agree that spinners really aren't useful (for anything that takes more than 5-10 seconds). Solution #2 from the post is what I want!

The progress bar for software updates and file transfers on macOS are infuriating. They’re decidedly unhelpful, and more often drastically wrong than anything I could imagine implementing myself. So wrong that it seems some significant improvements would be really low hanging fruit, if they cared to try:

- Doing anything with many smaller files will perform worse than fewer, larger files. Factor in a size/quantity multiplier/ratio on initial estimate. For APFS, I think the information needed should be available from init. For other file systems, this information should be gathered in a background process and feed the estimate as it accumulates.

- Revise the estimate more frequently, but not so frequently it produces pink noise. Apple’s progress bars notoriously get stuck for long periods, even hours. This isn’t just a bad user experience, it’s actually dangerous. Users frequently interrupt long running processes they perceive to be stalled, even if progress is ongoing but merely hard to observe. Swinging too far in the other direction at least gives an indication that something is happening, but the values become meaningless (I don’t know if this is still the case on Windows but I distinctly remember laughing uncontrollably watching estimates rapidly vacillate between seconds and hours, while overall progress appeared to have a steady pace).

- Revise the estimate based on expectations versus reality. As in, if your predetermined formula says 1000 small file operations take 15 seconds, but a comparable workload takes 30... and vice versa for large file operations... measure that! You don’t need machine learning for this, just a sufficiently proportionate time window to do some basic arithmetic.

- Provide additional observable feedback when these adjustments take place, and when there’s nothing to report other than something is taking a long time to generate more meaningful feedback. This doesn’t have to be ugly or noisy, it can be as simple as expanding the progress bar or messaging that progress is really ongoing even if you have no more information to report.

- Give us nerds a log! Please for the love of all that’s good in the world, let us see the sausage go through the grinder, even if we need to know a magic incantation to conjure it. And supplement it with a heartbeat message during long runs so we also don’t fall prey to dangerously assuming the process has stalled.

- I know Apple is notoriously minimalist in its UX style (most of the time), but maybe more information is sometimes actually less. As an example, major OS updates often quietly include multiple stages like firmware updates that require a reboot or temporarily disabling the display. These can be very alarming to users who don’t know what happened! Again, not just bad UX, it can be misleading and users may assume they’ve experienced failure or even an update loop that won’t terminate. A small amount of communication to set expectations could go a long way to alleviate that. A simple list of the overall steps and a bit of warning before a major visual disruption to observable progress would significantly reduce the chaotic list of assumptions users might be imagining.

- Maybe these updates are just too big, and doing too much at once. I mean, I understand that a major version update is going to have bigger subsystem impact, but maybe some of the ancillary stuff can be deferred. As an example, a major version update could get enough of the underlying update in place to get the machine in a usable state, then prioritize user land updates based on demand and run the rest in a background process.

- If you just don’t know, maybe it’s better to just be more vague. Apple popularized the spinner where progress is indeterminate. Use it as a last resort!

weeps in '1 minute remaining' apple update progress

> Estimating is hard.

More than hard, it is undecidable.

Reminds me of this xkcd: https://xkcd.com/612/

Progress bars are much better than spinners in many cases though, even if they lie, at least I get a rough estimation how long something is expected to take, and if it gets stuck.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact