logo
TrungTQ

Idempotency in Distributed Systems

  • Author: Administrator
  • Published On: 09 Jul 2025
  • Category: System Design

Idempotency in Distributed Systems and APIs

In the world of distributed systems and REST APIs , ensuring consistency and reliability is of utmost importance. One of the key concepts that helps achieve this is idempotency . This article will dive into idempotency, why it is needed, and how to implement it in practice.

What is idempotency?

Idempotency is a property of an operation that allows it to be performed multiple times without causing unwanted side effects. In other words, whether you call an idempotent operation once or multiple times, the end result should be the same.

For example, the assignment operation x = 5 is idempotent. No matter how many times you perform this assignment, the value of x will always be 5.

Conversely, the operation x = x + 1 is not idempotent. Each time this operation is performed, the value of x is increased by 1.

Why Is Idempotency Important?

In a distributed system, errors such as network disconnections, timeouts, or server failures can occur at any time. This can result in a request being sent multiple times without the client knowing.

If the operations are not idempotent, retrying requests can cause unwanted side effects, for example:

  • Duplicate transactions: An order can be created multiple times, resulting in the customer paying for multiple identical orders.
  • Update discrepancies: A record can be updated multiple times with different values, resulting in inconsistent data.
  • Overconsumption of resources: A resource can be consumed multiple times, causing resource depletion.

Idempotency helps solve these problems by ensuring that retrying requests does not cause unwanted side effects. This makes the system more reliable and predictable.

Idempotency Deployment Methods

There are different approaches to implementing idempotency, depending on the type of operation and system architecture. Here are some common approaches:

1. Idempotency Key

The Idempotency Key is a unique value generated by the client and sent with the request. The server uses this key to keep track of requests that have already been processed. When a request with an existing idempotency key is received, the server does not repeat the operation but only returns the result of the first attempt.

For example:

 POST /payments Content-Type: application/json Idempotency-Key: unique_payment_id_123 { "amount": 100, "currency": "USD" } In the above example, the client generates an idempotency key as POST /payments Content-Type: application/json Idempotency-Key: unique_payment_id_123 { "amount": 100, "currency": "USD" }

unique_payment_id_123 and send it in the Idempotency-Key header. The server will store this key along with the result of the payment request. If the client sends a request again with the same key, the server will return the stored result without re-executing the payment.

Advantage:

  • Simple and easy to deploy.
  • Works well with non-idempotent APIs.

Disadvantages:

  • Requires the client to create and manage idempotency keys.
  • The server must store the idempotency key and the corresponding result, which can be resource-intensive.
  • A garbage collection mechanism is needed to remove old idempotency keys.

2. Using Idempotent HTTP Methods

Some HTTP methods are defined as idempotent, for example: GET , PUT , DELETE . The server should ensure that these methods are truly idempotent.

  • GET: Get data. Doing it multiple times does not change the state of the server.
  • PUT: Replaces the entire resource. No matter how many times it is executed, the final state of the resource remains the same.
  • DELETE: Deletes a resource. After deletion, re-executing it does not cause side effects.

For example:

 PUT /products/123 Content-Type: application/json { "name": "Updated Product Name", "price": 200 } In the above example, the client uses PUT /products/123 Content-Type: application/json { "name": "Updated Product Name", "price": 200 }

PUT to update the product with ID 123. No matter how many times the client sends this request, the product will still have the updated name and value as above.

Advantage:

  • Take advantage of HTTP's built-in features.
  • Does not require the client to generate an idempotency key.

Disadvantages:

  • Only applicable to operations corresponding to idempotent HTTP methods.
  • Requires the server to strictly adhere to HTTP rules.

3. Use Optimistic Locking

Optimistic Locking is a technique that uses a version number or timestamp to check whether a record has been changed by another transaction before updating it.

When a client reads a record, the server returns the current version number of that record. When the client wants to update the record, it sends the old version number along with the changes. The server checks to see if the current version number of the record matches the version number the client sent. If it matches, the server updates the record and increments the version number. If it doesn't match, the server returns an error, indicating that the record was changed by another transaction.

For example:

 GET /products/123 Response: { "id": 123, "name": "Product Name", "price": 100, "version": 1 } PUT /products/123 Content-Type: application/json { "name": "Updated Product Name", "price": 200, "version": 1 } Response: { "id": 123, "name": "Updated Product Name", "price": 200, "version": 2 } In the above example, the client reads the product with ID 123 and receives the version number 1. Then, the client updates the product and sends the old version number (1) along with the changes. The server checks that the current version number of the product is still 1, so it updates the product and increases the version number to 2. GET /products/123 Response: { "id": 123, "name": "Product Name", "price": 100, "version": 1 } PUT /products/123 Content-Type: application/json { "name": "Updated Product Name", "price": 200, "version": 1 } Response: { "id": 123, "name": "Updated Product Name", "price": 200, "version": 2 }

If another client updates the product first, the version number will be incremented. When the first client sends an update request, the server will detect a version number mismatch and return an error.

Advantage:

  • Ensure data consistency.
  • Does not require the client to generate an idempotency key.

Disadvantages:

  • More complicated than other methods.
  • Can lead to contention if multiple clients update the same record.

4. Using Transactional Outbox Pattern

The Transactional Outbox Pattern is a pattern that ensures consistency between writing data to the database and sending messages to the message queue. Instead of sending messages directly after writing data to the database, you save messages to an "outbox" table in the same transaction. Then, another process reads the messages from the outbox table and sends them to the message queue.

Transactional Outbox Pattern

Advantage:

  • Ensure consistency between database and message queue.
  • Helps to handle errors related to sending messages.

Disadvantages:

  • More complicated than sending messages directly.
  • Requires an outbox table in the database.

Real Life Example

  • Stripe: Uses idempotency keys to ensure that payment requests are only processed once.
  • Amazon SQS: Provides message deduplication, which helps eliminate duplicate messages.
  • Kafka: Ensures that messages in a partition are delivered to consumers in the correct order and only once.

Frequently Asked Interview Questions

  • What is Idempotency and why is it important in distributed systems?
  • What are the common idempotency implementation methods?
  • When should idempotency keys be used?
  • How to ensure idempotency in a system with many services?
  • What are the advantages and disadvantages of using idempotent HTTP methods?
  • What problem does the Transactional Outbox Pattern solve?

Conclude

Idempotency is an important concept in distributed systems and APIs. Implementing idempotency helps ensure system consistency and reliability, especially in environments where failures can occur. By understanding the methods of implementing idempotency and applying them appropriately, you can build more robust and maintainable systems. To better understand system architecture, you can refer tosystem design .

  • Share On: