Code of the Day
IntermediateBetter Interfaces

Progress bars

Show the right feedback at the right time — progress bars for known totals, spinners for unknown waits.

UtilitiesIntermediate5 min read
By the end of this lesson you will be able to:
  • Explain when to show a progress bar versus a spinner
  • Describe what information a good progress bar conveys (count, total, percentage, ETA)
  • Understand why progress feedback reduces perceived wait time

Any operation that takes more than a second or two needs feedback. Without it, users cannot tell whether the program is working, stuck, or crashed. A blank terminal during a 30-second file scan feels broken even when everything is fine.

Bar or spinner?

The choice depends on one question: do you know the total?

Use a progress bar when you know how many items you will process. Scanning a list of 500 files, loading 1,000 database rows, downloading a file with a known size — all of these have a definite total. A bar can show 342/500 (68%) ETA 4s, which tells the user exactly where they are and when they will be done.

Use a spinner when the duration is unknown. Waiting for a network response, running a subprocess of unpredictable length, or polling until a condition is met — in these cases you cannot compute a percentage. A spinner honestly conveys "still working" without pretending to know more than it does. Showing a bar that jumps to 100% and then keeps spinning is worse than a spinner, because it lies.

What a good progress bar shows

A minimal progress bar shows a percentage. A good progress bar shows all of:

ColumnWhy it helps
Current countTells you exactly where you are: 342/500
Visual barGives an at-a-glance sense of how far along
PercentageQuantifies the bar: 68%
Elapsed timeConfirms the program is still running
ETATells you when to come back
Current itemShows the file/task being processed right now

Not all of these are always useful. For a two-second operation, ETA is noise. For a twenty-minute batch job, ETA is essential.

The psychology of waiting

Research on perceived wait time consistently shows that feedback makes waits feel shorter. Users who see a progress bar tolerate much longer waits than users who see nothing. The explanation is simple: uncertainty is stressful. A bar converts "I don't know what's happening" into "I know what's happening and approximately when it will end."

This is not a cosmetic concern. It is the difference between users trusting your tool and users killing the process and filing a bug report.

When to omit progress entirely

If the operation takes less than about 500 ms, a progress bar flashes briefly and vanishes — more disorienting than helpful. At that speed, just let it finish. Many CLI tools print a summary line after completion (Built 42 files in 0.3s) instead of showing a bar for very fast operations.

Never show a progress bar that does not move. A bar stuck at 0% for 30 seconds is more alarming than no bar at all. If you cannot update the bar during the operation (e.g. in a single blocking call), use a spinner instead.

Where to go next

Next: Rich progress — using rich.progress.track(), Progress(), and Console.status() to add the right kind of feedback to your tools.

Finished reading? Mark it complete to track your progress.

On this page