Thursday, 12 March 2026

how to control duplicate order

 Controlling duplicate orders is a common challenge in distributed systems, APIs, and microservices (especially in .NET Core + Angular + SQL Server architectures like yours). Duplicate orders usually happen due to:

  • User clicking “Place Order” multiple times

  • Network retries from client or gateway

  • Message queue retries

  • Concurrency issues in DB

  • API being called twice

Below are the most effective real-world solutions used in production systems. 🚀


1️⃣ Use Idempotency Key (Best Practice for APIs)

An Idempotency Key ensures that even if the request is sent multiple times, only one order is created.

Flow

  1. Angular generates a unique key (GUID).

  2. Send it in API header.

Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000
  1. API checks database/cache.

  • If key exists → return existing order.

  • If not → create order and store key.

Table Example

CREATE TABLE OrderRequests
(
    IdempotencyKey UNIQUEIDENTIFIER PRIMARY KEY,
    OrderId INT,
    CreatedDate DATETIME
)

.NET Core Example

[HttpPost]
public async Task<IActionResult> CreateOrder([FromHeader(Name="Idempotency-Key")] string key)
{
    var existing = await _db.OrderRequests
        .FirstOrDefaultAsync(x => x.IdempotencyKey == Guid.Parse(key));

    if(existing != null)
        return Ok(existing.OrderId);

    var order = new Order();
    _db.Orders.Add(order);
    await _db.SaveChangesAsync();

    _db.OrderRequests.Add(new OrderRequest
    {
        IdempotencyKey = Guid.Parse(key),
        OrderId = order.Id
    });

    await _db.SaveChangesAsync();

    return Ok(order.Id);
}

✅ Prevents duplicate orders even if API is called 10 times.


2️⃣ Unique Constraint in Database

Use unique index to prevent duplicate order creation.

Example:

CREATE UNIQUE INDEX UX_Order_User_Product
ON Orders(UserId, ProductId, OrderDate)

If duplicate request comes → SQL Server throws error.


3️⃣ Disable Button in Angular UI

Prevent multiple clicks.

isSubmitting = false;

placeOrder() {
  if(this.isSubmitting) return;

  this.isSubmitting = true;

  this.orderService.placeOrder().subscribe({
    next: () => this.isSubmitting = false,
    error: () => this.isSubmitting = false
  });
}

HTML:

<button [disabled]="isSubmitting">
Place Order
</button>

4️⃣ Optimistic Concurrency Control

Use RowVersion / Timestamp column.

ALTER TABLE Orders
ADD RowVersion ROWVERSION

Used when multiple users update same order.


5️⃣ Distributed Lock (Redis / Cache)

In high-traffic systems.

Example:

Lock Key = Order_UserId_ProductId

If lock exists → reject request.

Tools:

  • Redis

  • Azure Cache

  • Distributed Lock library


6️⃣ Message Queue Deduplication (Microservices)

If using Kafka / SQS / RabbitMQ

Use:

  • MessageId

  • DeduplicationId

  • Exactly-once processing

Example AWS SQS:

MessageDeduplicationId

Prevents duplicate message processing.


7️⃣ Pessimistic Locking (SQL Server)

SELECT * 
FROM Orders WITH (UPDLOCK, HOLDLOCK)
WHERE OrderId = @OrderId

Locks row until transaction completes.


8️⃣ Transaction Handling

Use transaction scope to ensure atomic operation.

using(var transaction = await _db.Database.BeginTransactionAsync())
{
   // create order
   // update inventory

   await transaction.CommitAsync();
}

🔥 Real Enterprise Approach (Used in Amazon / Uber)

They combine:

1️⃣ Idempotency key
2️⃣ Unique DB constraint
3️⃣ Distributed lock (Redis)
4️⃣ Retry-safe APIs

This guarantees exactly one order.


🎯 Interview Answer (Short)

Duplicate orders can be prevented using Idempotency Keys, Unique Database Constraints, Distributed Locks, and UI click prevention.
The most reliable solution is Idempotent APIs where each request contains a unique key and the server processes it only once.


✅ If you want, I can also explain 7 real production scenarios where duplicate orders happen in microservices and how companies solve them (very useful for 40–60 LPA architecture interviews).

No comments:

Post a Comment

Recent Post

how to control duplicate order