Mastering Idempotency in Java Microservices: 6 Proven Strategies

This article explains the concept of idempotency in Java backend services, why it is essential for reliable microservice interactions, and presents six practical implementation schemes—including unique indexes, token mechanisms, pessimistic and optimistic locks, distributed locks, and state‑machine constraints—along with code examples and integration tips for Spring Boot projects.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Mastering Idempotency in Java Microservices: 6 Proven Strategies

1. Idempotency Overview

1.1 Deep Understanding of Idempotency

In computing, idempotence means that executing an operation multiple times yields the same result without additional side effects. In Java backend development, idempotency is achieved by ensuring method or service call results are deterministic regardless of repeat invocations.

Although this definition is common, real‑world services often encounter conflicts between the theoretical definition and business logic.

For example, a query interface that fails on the first call due to a bug may still return the same failure on retry, which is idempotent but not aligned with business expectations. Similarly, an order payment that initially fails due to insufficient balance will continue to return the same error after the user recharges, again matching the definition but violating business logic.

Therefore, idempotency solutions should focus on preventing undesirable side effects of duplicate requests, especially for write operations such as duplicate charges or refunds.

1.2 Necessity of Idempotency

In microservices and distributed architectures, a request often involves multiple services, and network glitches or system anomalies make 100 % success impossible. Retries are common and lead to duplicate requests.

Idempotent design is created to handle duplicate requests; a good idempotent solution guarantees expected results without side effects. Typical scenarios that generate duplicate requests include:

User unreliability : accidental or intentional repeated clicks.

Network unreliability : network jitter or gateway retries, especially when delivering messages via a queue.

Service unreliability : when downstream services timeout and the caller retries.

In my SpringCloud microservice column “Using RocketMQ to Implement Distributed Transactions” a bug caused by missing idempotent handling led to duplicate consumption and data inconsistency.

1.3 Idempotency and Concurrency

Concurrent write scenarios, such as rapid multiple form submissions, require idempotent handling to prevent unexpected results. Idempotency is not exclusive to concurrency; it is intended to identify and process duplicate requests, whether concurrent or not.

Even non‑concurrent duplicate submissions (e.g., two windows submitting the same parameters ten minutes apart) still need idempotent control.

In the internet domain, idempotency and concurrency are tightly related, leading some to think solving idempotency solves high concurrency.

2. Idempotency Key Design

The goal of idempotent design is to ensure that the same request is processed only once. This typically requires a unique identifier such as a token or business serial number, called an Idempotency Key.

An Idempotency Key has three essential properties: uniqueness, immutability, and transitivity.

Two design approaches exist:

Non‑business Idempotency Key : a UUID, timestamp, or business serial number that must be persisted on both sides to trace the request.

Business Idempotency Key : composed of business elements (e.g., userId + activityId) that can be derived from request parameters without separate persistence.

3. Implementation Schemes

Idempotent implementation ensures that identical requests are processed only once. Six common schemes are:

3.1 Unique Index

Rely on a database unique constraint to prevent duplicate rows. In high‑concurrency scenarios, only one thread succeeds while others receive a constraint violation.

Typical fields in a business transaction table include id, gmt_create, gmt_modified, user_id, out_biz_no, biz_no, and status. A composite unique index on user_id and out_biz_no effectively prevents duplicate inserts.

3.2 Token Mechanism

Generate a unique token (e.g., UUID) when the client loads a form, store it in Redis, and require the token with each submission. The server validates the token, processes the request, then deletes the token to prevent repeats.

3.3 Pessimistic Lock

// 1. Begin transaction
begin;

// 2. Query by idempotency key for update
record = select * from tbl_xxx where out_biz_no = 'xxx' for update;

// 3. Decision based on status
if (record.getStatus() != expected) {
    return;
}

// 4. Update record
update tbl_xxx set status = 'target' where out_biz_no = 'xxx';

// 5. Commit transaction
commit;

Pessimistic locks serialize access but may cause long waiting under high contention.

3.4 Optimistic Lock

// 1. Retrieve object with version
select * from tablename where id = xxx;

// 2. Update with version check
update tableName set quantity = quantity-#{quantity}, version = #{version}+1
where id = xxx and version = #{version};

Optimistic locks rely on a version field to ensure consistency without holding database locks.

3.5 Distributed Lock

Similar to pessimistic lock but implemented via a lightweight external lock (e.g., Redis). After acquiring the lock, the business logic runs; if lock acquisition fails, the request is rejected.

3.6 State Machine

For entities with a finite set of states, a state machine can enforce idempotency by ignoring transitions that would not change the state (e.g., releasing inventory that is already released).

update tableName set quantity = quantity-#{quantity}, status = #{update_status}
where id = #{id} and status = #{status};

3.7 Summary

The six schemes can be grouped into three technical routes: unique index, unique data (pessimistic/optimistic/distributed lock), and state‑machine constraints. In practice, a single scheme rarely suffices; combining unique indexes with transaction or lock mechanisms yields a complete idempotent solution.

4. Code Implementation

The dailymart-idempotent-spring-boot-starter package encapsulates the distributed‑lock and token mechanisms. Adding the dependency to a Maven pom.xml enables the component.

<dependency>
    <groupId>com.jianzh5</groupId>
    <artifactId>dailymart-idempotent-spring-boot-starter</artifactId>
    <version>${project.version}</version>
</dependency>

Apply the custom @Idempotent annotation on methods and specify IdempotentTypeEnum to select the desired scheme (TOKEN, PARAM, SpEL, etc.). Example for token‑based idempotency:

@PostMapping("/api/order/create")
@Idempotent(type = IdempotentTypeEnum.TOKEN,
            message = "Order is being created, please do not submit repeatedly")
public void create(@RequestBody OrderDTO orderDTO) {
    orderService.save(orderDTO);
}

For parameter‑based distributed lock:

@Idempotent(key = "#lockRequest.transactionId", type = IdempotentTypeEnum.PARAM)
@PostMapping("/api/order/update")
public void update(@RequestBody OrderDTO orderDTO) {
    orderService.update(orderDTO);
}

These implementations demonstrate how the DailyMart project integrates multiple idempotent strategies to ensure reliability and stability.

5. Conclusion

The article detailed various idempotent solutions in distributed systems and clarified the distinction between idempotency and concurrency. Generally, concurrency implies idempotency, but idempotency is not exclusive to concurrency. Combining several techniques—unique indexes, locks, and state‑machine constraints—is essential for a robust solution.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MicroservicesdatabaseIdempotencydistributed-systemsspring-boot
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.