Prompt and context
This question tests whether you can turn a transport-level latency optimization into a clear business security boundary. TLS 1.3 early data can be sent before a connection is fully established, and RFC 8470 explicitly calls out replay risk. Therefore request safety cannot be decided only from the HTTP method name. Cover request classes, state transitions, idempotency, caches and proxies, client retries, monitoring, and fallback.
What the interviewer is evaluating
- Whether you distinguish harmless repeated reads from repeated side effects.
- Whether you restrict early data to an explicit safe set and give uncertain requests an explainable rejection path.
- Whether 425, idempotency keys, deduplication, and retry backoff work together.
- Whether you can explain proxy chains, logs, metrics, rollback, and staged rollout controls.
Clarifying questions to ask first
Confirm which requests may carry early data, where TLS terminates, and whether proxies or message retries follow the edge. Which operations change balances, inventory, orders, permissions, or notifications? Does the business already have idempotency keys, a request-state table, and unique constraints? Do clients, SDKs, and gateways understand 425? Who retries, how many times, and with what exponential backoff and jitter? If deduplication storage is unavailable, should the service reject, fall back to a full handshake, or continue read-only traffic?
A 30-second answer framework
I would exclude side-effecting or unprovably idempotent requests from early data by default. The edge detects early data and passes a protected signal to the application; safe reads may continue, while orders, charges, and permission changes return 425 or require a full handshake. For writes that truly need low latency, the client supplies an idempotency key and the server uses a unique constraint and short-lived result state to persist “processing” and “completed.” Clients retry only responses that are explicitly retryable, with bounded exponential backoff and jitter. Roll out gradually and monitor duplicate execution, 425, retry volume, and business anomalies.
Step-by-step deep dive
1. Define the trust boundary for early data
Detect early data at the TLS termination layer and pass it through a protected internal signal; a public client must not be able to forge a “safe request” marker. Define whether proxies, caches, and service-to-service calls can copy or delay the request. Treat a missing signal or uncertain path as high risk by default.
2. Classify by business side effect
Stateless reads whose repeated result does not change resources are easier to accept. Creating orders, charging, decrementing inventory, changing permissions, sending messages, and calling external systems are replay-sensitive. Even PUT or DELETE must be checked against the actual implementation; POST is not automatically non-idempotent. The business state model and unique constraints determine the guarantee.
3. Design 425 and full-handshake fallback
Return 425 Too Early for paths that do not permit early data and document how the client completes a full handshake before resending. A gateway must not retry 425 forever. Record whether the original request may have reached the application so the edge and client do not each retry and amplify load. When client capability is unknown, explicit failure is safer than silent execution.
4. Use idempotency keys and a state machine
Bind an idempotency key to the tenant, operation type, and request-parameter digest. Persist processing, success, and failure states behind a unique constraint. One concurrent request owns the key; others read the state or wait for a bounded time, while a parameter mismatch is rejected. Set a retention period so old results do not outlive the business retry window. Database commit and external side effects still require an outbox, status polling, or compensating design.
5. Constrain retries and proxy behavior
Clients retry only when the response is retryable and the operation satisfies the idempotency rule, using truncated exponential backoff, jitter, and a total-attempt limit. Gateways, SDKs, and queue consumers must not stack unbounded retries; distinguish 425, connection failure, rate limiting, and business rejection. For high-value writes, let the client query idempotency-key status instead of resending the original side effect.
6. Monitor, roll out, and fall back
Start with read paths and a small tenant set, retaining switches by route, client, and region. Track early-data volume, 425 rate, duplicate-key conflicts, duplicate charges or inventory anomalies, retry amplification, full-handshake latency, and deduplication-store errors. If thresholds are crossed, stop rollout, disable early data, or force a full handshake, and retain audit samples to determine whether a request actually executed.
Model high-quality answer
I would treat early data as potentially replayable input, not as an ordinary HTTPS request. The edge detects and protects the signal; reads continue only when their risk is acceptable, while orders, charges, inventory, permissions, and external notifications return 425 and require a full handshake. For writes that need low latency, the client must send an idempotency key bound to the tenant, operation, and parameter digest. The server persists processing, success, and failure states behind a unique constraint and rejects parameter conflicts. Define retry conditions separately for 425, connection failure, and rate limiting; clients use bounded exponential backoff and jitter, while the gateway avoids infinite automatic retries. Roll out gradually and monitor 425, duplicate keys, duplicate business execution, retry amplification, fallback latency, and deduplication failures. Disable early data or force a full handshake on anomalies, then reconcile audit records.
Common mistakes
- Assuming encrypted TLS means early data cannot be replayed.
- Classifying only by method name instead of actual business side effects.
- Letting both gateway and client retry 425 without a bound.
- Omitting tenant and parameter binding from the idempotency key.
- Caching only success and ignoring processing state or retryable failure semantics.
- Measuring latency gains without duplicate charges, inventory anomalies, or retry amplification.
- Omitting route-level disablement, full-handshake fallback, and audit reconciliation.
Follow-up questions and responses
What is the difference between 425 and 429?
425 means the request arrived too early under the current early-data condition and should be sent again after a full handshake. 429 means the request hit a rate or quota limit. Their retry conditions, wait hints, and monitoring meanings differ, so they should not share one automatic retry branch.
What if the client does not support 425?
For critical write paths, reject early data at the gateway or force a full handshake instead of depending on client interpretation. Ship compatibility behavior in an upgraded SDK. Read-only paths may continue, but record client capability and the risk boundary.
Should a charge continue if the idempotency store is down?
Do not perform a high-risk side effect when deduplication cannot be proven. Return a retryable error, fall back to a full handshake and recheck, or convert the request to a queryable pending state. Choose based on the loss limit and recovery path.
Could an early-data request execute after the service returns 425?
There is a race in which the request has reached the application, so the application must recheck the early-data signal and idempotency state before performing the side effect. A 425 does not revoke an already-started operation. Commit side effects through the state machine and unique constraint, then use audit records to confirm execution.