Course contentsShow
← Node.js
Lesson 544 of 1,9806. Networking and HTTP FundamentalsFree lesson

HTTP Method Idempotency

Design API endpoints that strictly adhere to idempotency standards for safe retry behavior.

In this lesson, you will learn how to design API endpoints so that repeating the same request multiple times has the exact same side effect as a single request, ensuring your application remains reliable even when network conditions are unstable.

What is Idempotency?

In distributed systems, networks are unreliable. Sometimes a client sends a request, the server processes it, but the network cuts out before the client receives the 200 OK response. The client, not knowing if the action succeeded, might try again. Idempotency is the guarantee that making multiple identical requests yields the same server state as making a single request.

Mapping Methods to Idempotency

HTTP methods are categorized by their expected behavior:

  • Idempotent: GET, HEAD, PUT, DELETE, OPTIONS, TRACE.
  • Non-Idempotent: POST, PATCH.

For example, a DELETE request for /users/123 is idempotent. Whether you delete the user once or five times, the result is the same: the user is gone. However, a POST request to /orders is not idempotent. If you resend it due to a timeout, you might accidentally create five separate orders for the same item.

Designing for Idempotency in Node.js

To handle non-idempotent operations like POST safely, we often use Idempotency Keys. A client generates a unique ID (like a UUID) and includes it in a header, such as Idempotency-Key: <unique-id>.

// Example of a basic idempotency check
app.post('/payments', async (req, res) => {
  const idempotencyKey = req.headers['idempotency-key'];
  
  // Check if we already processed this key
  const existingResult = await database.findProcessedKey(idempotencyKey);
  if (existingResult) {
    return res.status(200).json(existingResult.response);
  }

  // Otherwise, process the payment
  const result = await processPayment(req.body);
  
  // Store the key and the result for future retries
  await database.saveProcessedKey(idempotencyKey, result);
  
  res.status(201).json(result);
});

By storing the key, you ensure that if the client retries the exact same request, your server detects the key, skips the logic, and returns the cached result. This prevents duplicate actions and maintains data integrity despite flaky connections.

Key Takeaway: Design your API so that multiple identical requests produce the same state change, using custom headers like Idempotency-Key to safely handle retries for non-idempotent methods.