HTTP 425 Too Early
HTTP 425 Too Early means the server refused to process a request because it arrived in TLS 1.3 early data (0-RTT) and the server is unwilling to risk a replay attack. TLS 1.3 allows clients to send application data in the first flight of a resumed handshake — before the handshake is complete — but this creates a window where an attacker who captured that first flight could replay the same data to the server. A server that receives a non-safe, non-idempotent request in early data returns 425 to tell the client to wait for the handshake to complete and retry normally.
Quick reference
| Code | 425 |
|---|---|
| Name | Too Early |
| Category | 4xx Client Error |
| Specification | RFC 8470 |
| Context | TLS 1.3 0-RTT (early data) connections only |
| Client action | Retry after TLS handshake completes; do not retry in early data |
| Cacheable? | No |
TLS 1.3 0-RTT and the replay problem
TLS 1.3 introduced 0-RTT (zero round-trip time) resumption as a performance optimization. In a standard TLS 1.3 handshake, the client and server exchange messages over 1 round trip before application data can be sent. In 0-RTT resumption, a client that has previously connected to a server can include application data in the very first message of the handshake — before any server response — reducing latency by one full round trip.
The security tradeoff: data sent in the 0-RTT early data flight is vulnerable to replay attacks. An attacker who captures the initial TLS handshake record containing the early data can re-send it to the server at a later time. The server has no way to distinguish a legitimate first request from a replayed copy, because 0-RTT resumption does not provide anti-replay guarantees by default.
For safe and idempotent requests (GET, HEAD, OPTIONS), replay is acceptable: fetching the same resource twice has no side effects. For non-safe requests (POST, PUT, DELETE, PATCH), replay can cause serious problems: a payment might be charged twice, a record might be created twice, a delete might be re-executed.
The Early-Data header and 425
RFC 8470 defines a mechanism for HTTP over TLS 1.3 to handle 0-RTT requests safely:
The Early-Data request header: When an HTTP client sends a request in TLS 1.3 early data, it adds Early-Data: 1 to the request headers. This signals to the server (and any intermediaries) that the request arrived in early data and may be subject to replay.
Server policy: A server that does not want to process requests in early data returns 425 with no body. The client sees 425 and retries after the TLS handshake completes (without the Early-Data header).
POST /api/payments HTTP/1.1
Host: api.example.com
Early-Data: 1
Content-Type: application/json
{"amount": 100, "currency": "USD"}
HTTP/1.1 425 Too Early
[Client waits for handshake completion, then retries:]
POST /api/payments HTTP/1.1
Host: api.example.com
Content-Type: application/json
{"amount": 100, "currency": "USD"}
HTTP/1.1 201 Created
Server configuration
nginx: nginx supports TLS 1.3 0-RTT. To reject early data requests with 425 for specific locations:
server {
ssl_early_data on; # Accept 0-RTT at TLS level
location /api/payments/ {
# Reject early data for payment endpoints
if ($ssl_early_data) {
return 425;
}
proxy_pass http://payment_backend;
}
location /static/ {
# Safe to serve from early data (idempotent reads)
# No 425 rejection needed
}
}
Cloudflare: Cloudflare supports 0-RTT and passes the Early-Data header to origin servers. Origins can check for this header and return 425 for sensitive endpoints.
Application level:
app.post('/api/payments', (req, res) => {
if (req.headers['early-data'] === '1') {
return res.status(425).json({
error: 'too_early',
message: 'Retry after TLS handshake completes.'
});
}
// process payment...
});
When 425 appears in practice
425 is only relevant in environments where TLS 1.3 0-RTT is enabled. The conditions for encountering 425:
The client must support TLS 1.3 with 0-RTT (all modern browsers and curl with OpenSSL 1.1.1+ support this). The client must have a session ticket from a previous connection to the same server (required for resumption). The client must send early data in the resumed handshake (browser behavior depends on whether the prior visit established a resumption ticket). The server must be configured to reject early data for certain endpoints.
In practice, 425 is rare in server logs because: most clients that support 0-RTT also handle the retry correctly and transparently, browsers may not send POST/PUT/DELETE in early data, and many servers either do not enable 0-RTT or accept all early data requests and rely on application-level idempotency.
425 vs 503 vs 429
| Code | Meaning | Client action |
|---|---|---|
| 425 | Too Early (0-RTT replay risk) | Retry after TLS handshake completes |
| 503 | Service Unavailable | Retry after Retry-After interval |
| 429 | Too Many Requests | Retry after Retry-After interval (rate limit) |
Frequently asked questions
What does HTTP 425 mean?
The server received the request in TLS 1.3 early data (0-RTT) and refused to process it due to replay attack risk. The client should wait for the TLS handshake to complete and then retry the request without the Early-Data: 1 header.
Will I see 425 in a browser?
Rarely. Modern browsers handle 0-RTT retry transparently: when the server returns 425, the browser retries automatically after handshake completion without surfacing the error to the user. You are more likely to see 425 in custom HTTP client code or server logs.
Is GET safe to send in TLS 1.3 early data?
In principle yes — GET requests are safe and idempotent, so replay has no harmful side effects. Servers typically accept GET requests in early data and reserve 425 for unsafe methods (POST, PUT, DELETE, PATCH). However, this is a server policy decision.
How do I disable 0-RTT to avoid 425 entirely?
On nginx: ssl_early_data off; disables 0-RTT session resumption, eliminating the possibility of early data requests and 425 responses. The trade-off is losing the latency benefit of 0-RTT for returning visitors.
Related guides
Standards reference
Definitions from the IANA HTTP Status Code Registry and RFC 8470. Human-readable guidance by ErrorLookup. · HTTP 425 quick reference →