Skip to content

102 Processing

What is HTTP 102 Processing?

102 Processing
Sometimes you ask a computer to do something that takes a really long time, like...
HTTP 102 Processing status code illustration

Explain Like I’m 3

You asked someone to do something hard that takes a long time. They say ‘I’m still working on it!’ so you know they didn’t forget. They’re letting you know they’re busy doing what you asked!

Example: You ask your parent to build a big blanket fort. They say ‘I’m working on it!’ every few minutes so you know they’re still building it and haven’t stopped.

Explain Like I’m 5

Sometimes you ask a computer to do something that takes a really long time, like preparing a big list of all your photos. The computer says ‘102 Processing’ to tell you ‘I got your request and I’m working hard on it, please wait!’ It’s like a progress update so you know the computer didn’t freeze or forget what you asked for. This way you don’t get worried and click the button again.

Example: You ask a website to create a big photo album with 1000 pictures. It takes a while, so every 30 seconds the website says ‘102 Processing - Still working on your album!’ so you know it’s still going and didn’t break.

Jr. Developer

HTTP 102 Processing is an informational status code that tells the client the server has received the full request and is processing it, but the response isn’t ready yet. It’s used for long-running operations to prevent client timeouts. The server sends 102 periodically (e.g., every 20-30 seconds) during processing to keep the connection alive. Originally defined in RFC 2518 for WebDAV operations, it was deprecated in RFC 4918 but is still used in practice by services like Cloudflare. Modern usage includes long-polling, server-side rendering with slow data sources, or batch processing operations.

Example: Your API endpoint processes a large CSV file upload that takes 90 seconds. Without 102 responses, the client might timeout after 60 seconds and retry, creating duplicate work. By sending 102 Processing every 20 seconds, you signal that work is ongoing, preventing timeouts.

Code Example

// Node.js sending 102 Processing during long operation
app.post('/process-video', async (req, res) => {
const videoId = req.body.videoId;
// Send 102 every 20 seconds during processing
const interval = setInterval(() => {
res.writeProcessing(); // Sends 102 Processing
}, 20000);
try {
const result = await processVideo(videoId); // Takes 60s
clearInterval(interval);
res.status(200).json(result);
} catch (error) {
clearInterval(interval);
res.status(500).json({ error: 'Processing failed' });
}
});

Crash Course

102 Processing is an interim informational response indicating the server has received the complete request and is processing it, but no final response is available yet. It was originally specified in RFC 2518 for WebDAV (Web Distributed Authoring and Versioning) to handle operations involving multiple file operations that could take considerable time. The status was deprecated in the 2007 revision (RFC 4918), but remains in the HTTP status code registry and sees practical use. The primary purpose is preventing client timeouts during long-running operations by providing periodic keep-alive signals. Servers typically send 102 responses at regular intervals (20-100 seconds, depending on timeout configurations) during processing. CDNs like Cloudflare use 102 to signal that origin servers are still processing, preventing the CDN from timing out. Unlike 100 Continue (which is sent before reading the request body), 102 is sent after receiving the full request while processing it.

Example: A video transcoding API receives a request to convert a 4K video to multiple formats. The process takes 3 minutes. The server sends 102 Processing every 30 seconds. At second 30, 60, 90, 120, and 150, clients receive 102 responses, so they know processing continues. At second 180, they receive 200 OK with the transcoded video URLs. Without 102, most HTTP clients would timeout around 60-90 seconds.

Code Example

// Advanced 102 Processing with custom intervals
const express = require('express');
const app = express();
app.post('/api/bulk-process', async (req, res) => {
const items = req.body.items; // 1000 items
let processedCount = 0;
// Send 102 every 25 seconds OR every 100 items
let lastUpdate = Date.now();
const UPDATE_INTERVAL = 25000; // 25 seconds
const maybeSignalProcessing = () => {
const now = Date.now();
if (now - lastUpdate >= UPDATE_INTERVAL) {
// Node.js built-in method for 102
res.writeProcessing();
lastUpdate = now;
console.log(`Sent 102 Processing (${processedCount}/${items.length})`);
}
};
try {
for (const item of items) {
await processItem(item); // ~500ms each
processedCount++;
if (processedCount % 100 === 0) {
maybeSignalProcessing();
}
}
// Final response
res.status(200).json({
message: 'Batch processing complete',
processed: processedCount
});
} catch (error) {
res.status(500).json({
error: 'Processing failed',
processedCount
});
}
});
function processItem(item) {
return new Promise(resolve => setTimeout(resolve, 500));
}

Deep Dive

The 102 Processing status code was introduced in RFC 2518 (February 1999) as part of WebDAV extensions to HTTP/1.1. It addresses a specific problem: WebDAV operations like MOVE, COPY, or PROPFIND could involve recursing through large directory trees, potentially taking minutes to complete. Without interim responses, clients would timeout and retry, creating duplicate work or corrupting state. RFC 2518 specified that servers SHOULD send 102 if processing will exceed 20 seconds. The status was deprecated in RFC 4918 (June 2007) during WebDAV revision, though no replacement mechanism was provided. Despite deprecation, 102 remains in the IANA HTTP Status Code Registry and sees continued real-world use.

Technical Details

Protocol semantics of 102 are nuanced. It’s an interim informational response, not a final status. Multiple 102 responses may be sent for a single request. Clients must not cache 102 responses. The server must eventually send a final status code (2xx, 4xx, 5xx). Unlike 100 Continue (which requires client initiation via Expect header), servers send 102 unilaterally based on processing duration.

Proxy and gateway handling: Proxies may generate 102 responses themselves to prevent downstream timeouts, even if the origin server doesn’t. This is common in CDN architectures. Cloudflare, for instance, recommends origin servers send 102 at least every 100 seconds to prevent Cloudflare’s 100-second connection timeout. The hop-by-hop nature means intermediate proxies can suppress, generate, or forward 102 responses independently.

HTTP/2 and HTTP/3 implications: These protocols handle long-running requests differently through stream multiplexing and flow control. The need for 102 is reduced but not eliminated. Some implementations use HEADERS frames with HTTP status 102 on HTTP/2 streams to signal ongoing processing.

Client support varies significantly. Most browsers don’t expect or handle 102 responses - they’re designed for page loads, not long-running operations. However, programmatic HTTP clients (curl with —raw, Node.js http module, Python requests with stream=True) can receive and process 102 responses. Many client libraries silently ignore unrecognized 1xx responses, providing backward compatibility.

Alternative patterns have emerged: WebSockets for bidirectional communication with progress updates, Server-Sent Events (SSE) for unidirectional progress streaming, Long-polling with partial results, and Job queue patterns with separate status check endpoints. Each has trade-offs. 102 Processing remains the simplest for operations that must complete in a single HTTP request/response cycle.

Security and abuse considerations: Malicious servers could send infinite 102 responses to keep connections open indefinitely. Clients should implement absolute timeouts (not just idle timeouts). Rate limiting on 102 responses may be warranted to prevent abuse.

Code Example

// Production-grade 102 Processing implementation
const http = require('http');
class ProcessingSignaler {
constructor(res, options = {}) {
this.res = res;
this.interval = options.interval || 20000; // 20 seconds default
this.maxSignals = options.maxSignals || 50; // Prevent infinite 102s
this.signalCount = 0;
this.timer = null;
this.startTime = Date.now();
}
start() {
this.timer = setInterval(() => {
if (this.signalCount >= this.maxSignals) {
console.warn('Max 102 signals reached, stopping');
this.stop();
return;
}
try {
// Check if response is still writable
if (this.res.headersSent && !this.res.writableEnded) {
this.res.writeProcessing();
this.signalCount++;
const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
console.log(`Sent 102 Processing #${this.signalCount} (${elapsed}s elapsed)`);
} else {
this.stop();
}
} catch (error) {
console.error('Error sending 102:', error);
this.stop();
}
}, this.interval);
}
stop() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
}
const server = http.createServer(async (req, res) => {
if (req.url === '/long-process' && req.method === 'POST') {
// Initialize 102 signaler
const signaler = new ProcessingSignaler(res, {
interval: 25000, // 25 seconds
maxSignals: 20 // Max 20 * 25s = 500s total
});
signaler.start();
try {
// Simulate long-running operation
const result = await performLongOperation(req);
// Stop signaling before sending final response
signaler.stop();
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
success: true,
result,
processingTime: Date.now() - signaler.startTime,
signalsSent: signaler.signalCount
}));
} catch (error) {
signaler.stop();
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
error: error.message,
processingTime: Date.now() - signaler.startTime
}));
}
} else {
res.writeHead(404);
res.end('Not Found');
}
});
async function performLongOperation(req) {
// Simulate 90-second operation
await new Promise(resolve => setTimeout(resolve, 90000));
return { data: 'Processed successfully' };
}
server.listen(3000, () => {
console.log('Server with 102 Processing support running on port 3000');
});

Frequently Asked Questions

Is 102 Processing still valid to use even though it's deprecated?

Yes, it's deprecated in the WebDAV spec (RFC 4918) but remains in the IANA HTTP Status Code Registry and is still used in production by major services like Cloudflare and Node.js. It's particularly useful for preventing timeouts during long-running operations, and no official replacement was provided when it was deprecated.

How is 102 Processing different from 100 Continue?

100 Continue is sent BEFORE the server reads the request body, asking the client to proceed with sending it. 102 Processing is sent AFTER receiving the full request, while the server is processing it. 100 prevents wasting bandwidth on rejected requests; 102 prevents client timeouts during long processing.

How often should I send 102 Processing responses?

The original RFC 2518 suggested every 20 seconds if processing exceeds that duration. In practice, intervals of 20-30 seconds work well for most HTTP clients. For Cloudflare origins, send at least every 100 seconds to prevent their timeout. The key is staying under your client's timeout threshold.

Do browsers support 102 Processing responses?

Most browsers don't explicitly handle 102 responses since they're designed for page loads, not long-running operations. Browsers typically ignore unrecognized 1xx responses. However, programmatic HTTP clients (curl, Node.js, Python requests) can receive and process them properly.

What are alternatives to using 102 Processing?

Alternatives include: WebSockets for bidirectional real-time updates, Server-Sent Events (SSE) for unidirectional progress streaming, async job queues with separate status-check endpoints (POST creates job, GET checks status), or long-polling with partial results. Each has trade-offs; 102 is simplest for synchronous request/response cycles.

Common Causes

  • WebDAV operations (COPY, MOVE, PROPFIND) on large directory trees
  • Long-running server-side video/image processing or transcoding
  • Batch processing of large datasets in a single HTTP request
  • Complex database queries or aggregations taking over 20 seconds
  • Server-side rendering with slow external API dependencies
  • CDN origin servers signaling to CDN that processing continues

Implementation Guidance

  • Server-side: Use res.writeProcessing() in Node.js or equivalent in your framework
  • Send 102 responses at regular intervals (20-30 seconds recommended)
  • Set a maximum number of 102 signals to prevent infinite loops
  • Stop sending 102 before sending the final status code
  • Client-side: Configure appropriate timeouts to allow for long operations
  • Consider alternatives if processing exceeds 2-3 minutes (async jobs, WebSockets)
  • For Cloudflare origins: Send 102 at least every 100 seconds
  • Implement absolute timeouts (not just idle timeouts) to prevent abuse
  • Log 102 signals for monitoring long-running operation patterns
📚 Sources:
🕐 Last updated: January 5, 2026

Comments