Making a 10-second AI wait feel fast.
Your new AI feature works. It also takes twelve seconds — and every loading pattern in your toolkit was designed for three hundred milliseconds. The spinner that was fine for a network call becomes a trust problem at that length. Here's what survives the jump from milliseconds to seconds, and what has to be replaced.
This wait is a different species
Jakob Nielsen published the three response-time limits back in 1993, and they haven't moved: around a tenth of a second feels instant, around one second keeps the user's flow of thought intact, and around ten seconds is the outer limit for holding attention on the task at all. Almost everything we call "loading UX" — spinner delays, skeleton screens, optimistic updates — was built for the space between the first two numbers. A single LLM call routinely blows through the second one, and a multi-step pipeline — a vision pass, then copywriting, then image generation — lives past the third. Past ten seconds users don't just get impatient; they self-interrupt. They switch apps, and your job finishes in a room nobody is standing in. Designing that wait is not a polish task. It decides whether the feature gets used twice.
Stream anything a human can read
The single biggest lever costs no design at all. An LLM produces its answer one token at a time, and the time to the first token is a small fraction of the time to the last. A completion that takes fifteen seconds to finish often starts arriving in under two. If you show tokens as they arrive, the perceived wait collapses to first-token latency, because reading keeps pace with generation — the user is never waiting for the model, they're keeping up with it.
This isn't only for chat apps. Any prose-shaped output — a generated description, captions, release notes, a translation — can stream into the field it will live in. The awkward case is structured output: JSON that drives a layout can't be dumped on screen half-parsed. There you have two options. Parse incrementally and populate each part of the UI as its field closes, or split the request — ask the model for the fast, user-visible piece first and fetch the rest in a second call while the user is already looking at something.
Every loading state makes a promise
A spinner promises "this is too quick to be worth explaining." That's true at 800 milliseconds and a lie at twelve seconds — an unchanging spinner carries no news, and at some point no news reads as stuck. A skeleton screen promises a shape: it works when you know what's coming, like a list of cards. But AI output often decides its own shape, and a skeleton guessing at three gray lines when the model may return something else entirely is a promise you can't keep. And a determinate progress bar promises a denominator. You don't have one — you don't know how many tokens are coming. Bars animated on a timer inevitably stall near the end, and a bar that sits at 90% for eight seconds teaches the user permanently that your progress indicators mean nothing.
Honest theater: label the real stages
The pattern that actually fits a multi-second pipeline is a staged status label: name the real steps of the work as they happen. When ShotCanvas generates a screenshot set, the wait screen steps through "Reading your screenshots," "Designing your layout," "Writing your captions" — which is literally the pipeline: a vision pass, a layout pass, a copy pass. Two implementation details are worth stealing. First, the early steps advance on a short timer so the screen feels alive, but the sequence holds on the stage where the pipeline genuinely spends its time — it never ticks to done on a schedule. Second, the final stage ("Creating your backdrop") lights up only when a flag from the real job says that work has started, never on a timer.
The line we drew, and recommend: motion may be theatrical, claims must be true. Pulse, shimmer, animate as much as your brand can carry. But never display a stage your pipeline doesn't have, and never mark work finished that isn't — the one time the output contradicts the label, the label dies forever.
Block the result, not the app
The most expensive mistake at this duration isn't visual, it's modal. A full-screen blocking overlay holds the entire app hostage to one feature's latency. Block only the surface where the result will land and leave everything else usable — at ten-plus seconds, some users will go do something else, and that should be allowed rather than punished. That implies the job must survive navigation: if the user backs out and returns, reattach to the running job and show its live progress instead of cancelling it or, worse, starting a duplicate. And disable the trigger while it runs — a button that still says "Generate" mid-generation invites a retry tap, which on a paid API is duplicate spend and a duplicate result.
Say how long, and mean it
If the typical run takes around twenty seconds, say "about 20 seconds" before the user commits. The number can be rough; it has to be honest. A wait with a known size is something a user can decide to sit through — an open-ended one is something they endure, and resent. Two smaller courtesies belong in the same pass: honor prefers-reduced-motion, because twelve seconds is a very long time to show someone animation they asked not to see, and put the stage label in a polite live region so screen-reader users hear the progress sighted users watch.
One last reframe. A multi-second wait is the only moment in your app where the user stares at one screen with full attention and nothing to do. That's an argument for making it a branded moment rather than a system spinner — but polish is the top coat. Honesty about what's happening, streaming what can stream, and leaving the user unblocked are the primer. Get those wrong and no amount of shimmer saves the feature.
See one in the wild
The staged wait described above is the one ShotCanvas shows while its AI reads your raw screenshots, composes a template set, and writes the captions. Watch what it does at each stage — where it holds, what it never claims — then steal the pattern for your own features.