# Loading states in AI interfaces: what to show while the model thinks

> What to show while an AI model responds: spinner, skeleton, real steps or a progress bar, depending on how long the wait lasts and what the NN/g guidelines say.

*Tags: ai, ux, interfaces, states*

---


> [!info] Quick Definition
> A **loading state in an AI interface** is what the screen shows while a model generates a response or runs a task. Its job is to tell people the system is still working, give a sense of how much is left, and stop them from thinking the app has frozen.


## Why is it different in AI?

In a traditional app, a load usually lasts milliseconds or a few seconds, and it is known in advance. In AI, a response can take two seconds or twenty. The duration changes with the length of the text, the provider's load and, in an agent, the number of steps it takes.

That uncertainty changes the choice. A spinner only says "wait", without saying how long. And a screen with no signal for several seconds leads people to reload or repeat the action, which in AI often means paying twice for the same answer.

The baseline rules come from Nielsen Norman Group (NN/g) and were written for page loads, not AI, but the principle carries over: the form of the state should match the wait. According to NN/g:

- Under 1 second, you need neither a spinner nor a skeleton.
- Spinners work best on a single module and for waits of 2 to 10 seconds.
- Skeleton screens are preferred over spinners when a full screen is loading and the wait is under 10 seconds, because they show the page layout and reduce perceived loading time.
- Beyond 10 seconds, a progress bar is recommended, and the wait needs an explicit estimate of its duration.

## Which state to use for which wait?

| Wait | Recommended state | Why |
|---|---|---|
| Under 1 second | Nothing, or a subtle change in the button | An indicator only adds flicker |
| 2 to 10 seconds, one block | Spinner or pulsing dots, with a short text | Signals work without promising a time |
| Long text answer | Text streaming, with a brief indicator at first | People read while it arrives |
| Full view with a known structure | Skeleton of the structure | Anticipates the shape of the result |
| More than 10 seconds or a multi-step task | Real steps, progress bar or estimate | Shows it is moving and what is left |

AWS's Cloudscape design system, in its progressive steps pattern for generative AI, uses the same 10-second cut. Below it, it recommends a loading status on the last step, with extra detail if possible. Above it, a time estimate when the wait is indeterminate and a progress bar when it can be measured. It also advises against showing a loading state for waits under one second, because it flickers, and suggests starting to show the text if the model streams quickly.

One detail is often missed: the wording of the state. NN/g recommends pairing the animation with a phrase that explains the wait, such as "Loading comments…", and advises against a static "Loading…". In AI, "Thinking…" describes the model; "Searching your March invoices" describes the real work and lets the person judge whether it is going well.

## How do you show an agent's progress?

An agent that calls tools has real steps: reading a file, querying an API, writing a result. Show those steps in a short list, with their status (pending, running, done, failed). That way the wait stops being a black box. Cloudscape adds two useful details: the status of the main step should reflect its most urgent sub-step, and finished steps can stay in a collapsible section next to the final output.

Watch out for fake progress. A bar that fills with time, unrelated to the work, is lying. If you cannot measure progress, show steps instead of a percentage. If you have an estimate, label it as an estimate, for example "This step may take up to 15 seconds". NN/g also suggests keeping estimates generous: people tolerate a pleasant surprise better than a bar that stalls.

To understand why an agent produces intermediate steps, see the [[agent-loop|agent loop]]. When the person is waiting for text rather than steps, [[response-streaming|response streaming]] is usually better than any indicator. To see where the wait comes from, look at [[llm-latency|latency and tokens per second]]. And if the task is long and can run in the background, the page on [[background-agents|background agents]] describes that notification model.

## What happens if it takes too long?

Define a threshold before you ship the feature. For example (adjust the numbers to your case): at 10 seconds the message changes and offers to cancel; at 60 seconds it offers to continue in the background or retry. Without a threshold, the screen stays on "Loading" until the person gives up.

And always leave a way out. NN/g recommends giving a way to stop the process when an action takes a while. A cancel button, a retry, and a message that says what was lost and what is kept are worth more than any animation. NN/g also advises against "don't click again" warnings: it is better to show that the first click was registered. If the problem is an error rather than a wait, see [[ai-errors-and-recovery|AI errors and how to recover]].

## When should you NOT show a visible loading state?

When the response arrives in under a second, an indicator only adds flicker. And for actions that run in the background without the person waiting, a notification at the end is usually better than blocking the screen.

## How do you test a loading state with real people?

Loading states are best judged in use. Ask five people to wait for a real response without interrupting, and to say out loud what they think is happening. Three questions guide the observation:

1. Do they know the system is working at two seconds?
2. Do they know what to do if it takes twenty?
3. Do they understand what happened if it fails?

If someone thinks the app has frozen, the state is not communicating enough, even if it works technically. Also test with a screen reader: the state must be announced, not just seen (more in [[accessibility-in-ai-interfaces|accessibility in AI interfaces]]).

## Example

Illustrative example: a personal finance app generates a monthly summary with AI, and the first version shows a spinner for about 25 seconds. Past 10 seconds, the NN/g rules call for a progress bar or an estimate, and a spinner alone gives neither. It is reasonable to expect people to open the summary two or three times, creating duplicate requests.

The team replaces the state with a list of real steps: "Reading your transactions", "Grouping by category", "Writing the summary". Each step is checked off when it finishes. If one category takes too long, a notice appears with the option to keep waiting or cancel. To find out whether it worked, the team compares the share of summaries requested more than once before and after the change.

## Common mistakes

- Using the same spinner for everything, from a save to a five-minute analysis.
- Promising a time that is not met.
- Showing a percentage that does not match real work.
- Blocking the screen with no option to cancel.
- Writing "Loading…" without saying what is being done.
- Forgetting the error state: if the load fails, the message must say what happened and what to do.

## Sources

- [Skeleton Screens 101 (Nielsen Norman Group)](https://www.nngroup.com/articles/skeleton-screens/)
- [Progress Indicators Make a Slow System Less Insufferable (Nielsen Norman Group)](https://www.nngroup.com/articles/progress-indicators/)
- [Progressive steps, generative AI pattern (Cloudscape Design System)](https://cloudscape.design/patterns/genai/progressive-steps)


---

Source: https://www.fernandoux.com/en/wiki/ai/ai-loading-states/
