Backend Development 11 min read

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

This article explains how to achieve idempotent order creation and update by using unique order IDs, database primary‑key constraints, Redis flags, and a version‑column mechanism to detect and prevent duplicate submissions and ABA anomalies in distributed systems.

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

Problem Background

The simplest case is a DB transaction: when creating an order, inserts to the order table and order‑item table must be executed within the same transaction.

Order service calls Pay service; a network timeout triggers a retry, causing the Pay service to receive the same payment request twice, possibly on different nodes due to load balancing. Therefore, the distributed interface must guarantee idempotency.

How to Avoid Duplicate Orders

Front‑end can block repeated form submissions, but network errors and automatic retries in RPC frameworks or gateways mean duplicate requests cannot be fully prevented on the client side; the service must ensure idempotency.

2.1 How to Determine a Duplicate Request

Check the order table before inserting, but defining “duplicate order” in SQL is difficult.

Same user, product, and price may still be a legitimate consecutive order.

To guarantee idempotency, each request must have a unique identifier, e.g., an order_id that can be used only once for payment.

After processing a request, record a flag indicating the request has been handled, such as a status field in MySQL or a Redis key.

When a duplicate request arrives, the unique constraint on order_id causes the INSERT to fail, rolling back the transaction and preventing double charging.

Implementation steps:

Provide an "orderId generation" API that returns a globally unique order number.

The front‑end obtains this order number before submitting the order.

The order number becomes the primary key of the order table; duplicate INSERTs with the same primary key are rejected by the DB.

Optionally store the order ID in Redis (e.g., set order_id payed ) and check the value before processing.

Solving the ABA Problem

When a seller updates a tracking number, a sequence like 666 → 888 → retry of 666 can cause inconsistent data if the first 666 response is lost and the client retries.

Solution: add a version column to the order table. Each read returns the current version; the update request includes this version. The service updates only if the version matches and increments it atomically.

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

If the version has changed, the update fails, prompting the client to re‑fetch the latest data.

This version check prevents both cases of ABA: a stale 666 update is rejected, and a retry of 666 after a successful 888 will also be rejected because the version no longer matches.

Summary

Use pre‑generated unique order IDs and DB primary‑key constraints to make order creation idempotent.

Employ a version‑column mechanism for order updates to detect and prevent ABA anomalies, ensuring update operations are atomic and idempotent.

backendTransactionDatabaseIdempotencyABA problemduplicate-order
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.