A large cache clear can outlast the admin request which starts it. I split the work into bounded batches, give the operator visible progress and make interrupted runs recoverable. That keeps the interface responsive while showing whether the clear has actually finished.
Separate starting from finishing
The button should start a job and return its identifier. The interface can then ask for the current state. That lets me distinguish queued, running, complete and failed instead of leaving a spinner on screen until the browser gives up.
A timeout is particularly confusing when the server continues working after the browser has stopped waiting. People press the button again, and now several clears may be running together. I make repeated requests find the existing job or safely coalesce with it.
Bound the work in each batch
I put both a time budget and a practical batch size around each pass. The job saves its cursor and resumes later. Redis’s SCAN command supports incremental iteration, but its count is a hint rather than a promised number of keys. An empty result does not mean the scan has finished if the cursor is still non-zero.
SCAN may also return a key more than once. Deleting an already deleted cache entry is harmless, but my progress accounting must not treat every returned key as a unique discovery. I avoid presenting an exact percentage when I do not have a stable total.
Keep the scope and permissions
Moving work into the background does not remove the need for capability checks, a protected start action and a site-specific key namespace. The status endpoint should only expose the job information the current operator is allowed to see.
I keep the job’s scope fixed when it starts. A later settings change should not turn a clear for one site or cache family into a wider operation halfway through.
Completion means the work finished
The interface needs to show a real failure if the next batch cannot run, along with enough information to retry safely. It should not claim success merely because the job was accepted. I also separate clearing from warming: a cache can be empty successfully while the background refill is still working.
My test includes a job large enough to cross several batches, a refresh of the admin page halfway through, a repeated click and a worker interruption. If I can resume without losing the scope or lying about completion, the little button is finally doing an honest job.
For the publishing side of the same problem, I have written about keeping a sitemap aligned with what the site actually serves.