Back to Blog
InfrastructureTechnical Note

Running Website Analysis as an Async Job

I returned a job ID for website analysis, sent progress over WebSocket, and cleaned the page before analysis. The implementation ran in one Node process.

January 22, 20263 min read
Async JobsExpressWebSocketsWeb Scraping

A website-analysis endpoint had to fetch a page, clean its HTML, extract structure, and run several analysis steps. Returning all of that in one response kept the browser waiting without knowing which step had finished.

The endpoint returned a job ID

The Express controller normalized the submitted URL, created an analysis ID, and returned HTTP 202. A 250-millisecond timer then called the processing function. The browser had an ID to subscribe to while the analysis continued.

Express controller returning HTTP 202 with an analysis ID before starting website analysis.
In-process analysis job

The response calls the job queued. In this implementation, that means scheduled in the same Node process. The timer releases the HTTP response; it does not create a separate worker or persist the task across a restart.

WebSocket events carried status

The browser subscribed with the analysis ID. The server acknowledged the subscription and replayed the buffered events for that ID. This covered a timing problem: an analysis step could finish before the browser had opened its WebSocket.

WebSocket subscription handler associating a socket with an analysis ID and replaying events from an in-memory buffer.
Buffered status replay

The loop replays the buffered events. A reconnect can receive events it has already seen, so the frontend has to apply status updates without appending duplicate results. The buffer lasts only as long as the process that owns it.

Cut page chrome before sending content for analysis

Cheerio removed scripts, styles, navigation, footers, hidden elements, cookie notices, and matching advert or banner elements. The scraper extracted the title, description, headings, links, and cleaned body text rather than passing raw HTML into analysis.

Cheerio scraper removing page chrome and extracting structured website content.
Website cleanup

The extraction kept up to 50 absolute HTTP links and 12,000 characters of body text. Its word count came from that shortened text, not necessarily the full page. Those caps limited the payload, though a long page could lose content near the end.

Where this implementation stops

For restart recovery, the job and its results would need persistent storage and a worker queue outside this process.

The controller shows URL normalization, with no fetch-safety checks included. Accepting arbitrary URLs also requires checking private addresses and redirect destinations before making network requests.

Have a similar project?

Talk to Me