You ask an app to research ten pages. It returns “Started.” A little later, it returns “Finished.” You open the result and find two usable pages, three errors, and a blank summary.
Was the job successful? The background worker might be done, but the user still does not have the thing you promised.
On September 25, Cloudflare announced lifecycle events for Browser Run crawl jobs. A Queue subscription can receive crawl.started, crawl.updated, and crawl.finished events. That is a useful way to react to a crawl without repeatedly asking for its status.
The more interesting beginner lesson is about what happens after “finished.” If you build an AI feature that gathers pages, generates a report, processes a file, or sends a batch of messages, the status of the worker is only one piece of evidence. Your app still has to retrieve the output, check what worked, and show a truthful result.
In my freelance app work, I have learned to describe what a user can actually do at the end of a workflow. “The job ran” is an internal event. “You can open a report with three checked sources and see why two were excluded” is a user outcome.
If describing that outcome is the hard part of your first build, my $1 AI App Builder Starter Prompts can guide you through the initial workflow. Then use the checklist below to tell your AI coding tool what “done” must mean for any background task.
What the new events tell you
Cloudflare's crawl documentation describes a two-step process. Starting a crawl returns a job ID immediately. Later, you use that ID to get the job's status and results. The new events offer a push-based way to notice changes, but the event does not contain the crawled page content. After a crawl.finished event, you still fetch the results.
The event schemas make the distinction concrete. A crawl.finished payload includes a job status and counts for total, completed, errored, and skipped pages. Cloudflare's example even shows a job with two completed pages and one errored page. A finished crawl can therefore include incomplete source coverage.
Another detail matters if you run several jobs: Browser Run subscriptions are account-wide. A handler has to match the event's job ID to the request your app stored. It should not assume that the next event belongs to the user currently watching the screen.
I would not make a beginner adopt Queues just to build a first prototype. Polling a job-status endpoint can be enough at small scale. The lesson applies either way: a notification tells you to check the work, not to invent its outcome.
The five-check background job checklist
Imagine a small app that turns a public website into a research brief. A user submits a site, the app starts a crawl, and an AI tool summarizes what it finds. This is a hypothetical build example, not a claim about a client project.
Before I call that feature ready, I would run five checks.
1. Can you connect the result to the original request?
Save a record when the user starts the job: who requested it, the target site, when it began, and the provider's job ID. Show the user a pending state tied to that record.
When an event or status response arrives, look up the matching job ID. If it is unknown, do not attach it to whichever brief happens to be open. If the request was cancelled, do not quietly publish a late result as a fresh answer.
Test: Start two research jobs for different test users. Finish them in the opposite order. Each user should see only the result tied to their own request.
2. Did the job end, and how did it end?
“Not running” is not the same as “completed successfully.” Cloudflare documents terminal states that include timeout, account limits, user cancellation, and errors as well as completion. Your UI needs the distinction, even if the labels are simpler than the provider's labels.
Test: Give a test job a failed terminal state. The screen should show a failure or a clear next step, not a success checkmark.
3. How much of the requested work produced usable material?
A completed crawl can still have errored, skipped, or disallowed pages. Compare the final counts and examine the retrieved records. Decide the minimum usable coverage for your product before writing a summary.
For a research brief, I might allow a partial report if it clearly lists which sources were used and which were unavailable. If the missing page is the only source for an important claim, I would withhold that claim. That is a product rule I would choose, not a guarantee Cloudflare makes.
Test: Return two good records, one blocked page, and one empty record. The brief must cite only material it actually has and label its gaps.
4. Did the output make it into the product?
The crawl.finished event is a signal. The full page content comes from a later result request. Your app may then need to parse, summarize, save, and display it. A failure anywhere in that chain can leave a successful provider job with no usable user result.
Write down each state: waiting, collecting, processing, ready, and needs attention are one possible set. Move to ready only after the saved brief can be reopened. Refreshing the page is a cheap, useful proof that the result is durable.
Test: Interrupt processing after the crawl ends but before the brief is saved. The app should preserve the job ID and show a recoverable state, rather than claim the report is ready.
5. Can you explain the result without exposing too much?
Keep a narrow receipt: request ID, provider job ID, terminal status, source counts, result location, and the reason any sources were excluded. That helps you investigate a bad brief without copying entire crawled pages or user inputs into every log.
Cloudflare says Queues provides at-least-once delivery, so a consumer can occasionally receive a message more than once. Use the stored job ID and result record to recognize that repeat. The deeper duplicate-action design deserves its own review; for this checklist, the immediate question is whether a repeated finish signal can overwrite a good report with an empty one.
Test: Deliver the same finish signal twice. The user should still see one coherent report and one honest status.
A prompt to give your AI coding tool
Trace one background job from the user's click to the reopened result. List the request ID, external job ID, every status, where the full output is retrieved, the minimum usable result, and the exact point the UI says “ready.” Show what happens for a failed job, a partial result, a processing interruption, and a repeated completion signal. Propose the smallest change that makes the user-facing status truthful. Do not add a queue unless the existing flow needs one.
Run that prompt on one workflow, then try the five tests with disposable data. You can start with a simple status check and one stored result. Add event subscriptions when they solve a real waiting or coordination problem.
Cloudflare's release makes background work easier to observe. It does not change the definition of a useful app: the person who asked for the work should be able to open the result and understand what it contains.
If you want a guided first action, use my $1 AI App Builder Starter Prompts to write down one user request and its promised output, then apply this checklist to that path.
For the organized route from idea through scope, screens, build, QA, and publication, AI App Builder From Zero is my $9 e-book. All 40 Starter Prompts are included as a free bonus inside its PDF and EPUB, so you do not need the separate $1 pack if you buy the book.
Review Radar is coming soon: preview it and join the email waitlist. It is being built to turn research about an app idea into tailored screens and an AI-ready project folder. Those can make a first build concrete; they do not promise revenue, a finished app, or a background workflow that has passed the checks above. Checkout is not open.
The shortest version: do not mark a job complete until the user can open the result you promised.
You can also find me here:
Medium: https://medium.com/@marcusykim
DEV.to: https://dev.to/marcusykim
Website: https://marcusykim.com/
X: https://x.com/marcusykim
LinkedIn: https://www.linkedin.com/in/marcusykim/
Upwork: https://www.upwork.com/freelancers/marcusykim
Top comments (0)