Backend Development 11 min read

Ensuring Idempotency in Order Services: Preventing Duplicate Orders and Solving the ABA Problem

The article explains how to achieve idempotent order creation and updates by using unique order IDs, database primary key constraints, Redis flags, and a version column to prevent duplicate inserts and solve the ABA problem in distributed backend systems.

Top Architect
Top Architect
Top Architect
Ensuring Idempotency in Order Services: Preventing Duplicate Orders and Solving the ABA Problem

The simplest scenario for idempotency is a database transaction when creating an order: inserting rows into the order and order_item tables must occur within the same transaction.

When the Order service calls the Pay service, network timeouts can trigger retries, causing the same payment request to be received by different service instances. This requires the service interface to be idempotent.

Implemented with Spring Boot, MyBatis Plus, Vue & Element for a backend management system supporting RBAC, multi‑tenant, workflow, third‑party login, payment, SMS, and e‑commerce features.

To avoid duplicate orders, each request should carry a unique identifier (e.g., a globally unique order ID). The order ID can be used as the primary key; the database’s unique constraint ensures that only one INSERT succeeds.

After generating an order ID, the frontend includes it in the order‑creation request. If the same ID is submitted again, the database rejects the duplicate INSERT due to the primary‑key constraint.

For additional safety, a Redis key (e.g., set order_id payed ) can be set after a successful payment record insertion. Subsequent requests check this key; if the value is payed , the request is ignored.

If a duplicate order causes an INSERT into t_order to fail, the Order service should still return a success response to the client to avoid confusing the user.

Implemented with Spring Cloud Alibaba, Gateway, Nacos, RocketMQ, Vue & Element for a similar backend system.

To solve the ABA problem during order updates, a version column is added to the order table. The client sends the current version with the update request.

The service checks the version: if it matches, the update proceeds and the version is incremented atomically within the same transaction; otherwise, the update is rejected.

UPDATE orders set tracking_number = 666, version = version + 1 WHERE version = 8;

This mechanism guarantees that concurrent updates cannot overwrite each other, preventing the ABA scenario where a stale update would incorrectly revert data.

In summary, idempotent order creation can be achieved by pre‑generating a unique order ID and leveraging the database’s primary‑key uniqueness, while idempotent updates are ensured by version‑based optimistic locking, both of which can be applied to other services that rely on database persistence.

BackendTransactionDatabaseIdempotencyVersioningABA
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login 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.