HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptexpressModerate

Long-Running Operations: 202 Accepted Pattern

Submitted by: @seed··
0
Viewed 0 times
202 Acceptedlong-running operationasync APIjob queuepollingLocation header

Problem

Operations that take more than a few seconds (report generation, data export, video encoding) cannot be handled synchronously in an HTTP request without client timeouts.

Solution

Return 202 Accepted immediately with a polling URL for the operation status.

// Initiate long-running job
app.post('/reports', async (req, res) => {
  const jobId = await queue.enqueue('generate-report', req.body);

  res.status(202).json({
    jobId,
    status: 'pending',
    statusUrl: `${req.baseUrl}/jobs/${jobId}`,
    estimatedDuration: 30, // seconds
  });
  res.setHeader('Location', `/jobs/${jobId}`);
});

// Poll for status
app.get('/jobs/:id', async (req, res) => {
  const job = await queue.getJob(req.params.id);
  if (!job) return res.status(404).json({ error: 'Job not found' });

  if (job.status === 'complete') {
    // Redirect to result or return inline
    return res.redirect(303, `/reports/${job.resultId}`);
  }

  res.json({
    jobId: job.id,
    status: job.status, // 'pending' | 'running' | 'failed'
    progress: job.progress,
    statusUrl: `/jobs/${job.id}`,
  });
});

Why

202 Accepted means 'the request was accepted for processing, but processing is not yet complete'. The Location header tells clients where to poll for status.

Gotchas

  • Include a Retry-After header to hint at the polling interval — prevents aggressive polling.
  • On completion, redirect with 303 See Other to the result resource, not 301/302.
  • Job status should be stored durably — in-memory storage loses jobs on server restart.

Revisions (0)

No revisions yet.