You are here: Home / Topics / How to create Idempotent in your code?

How to create Idempotent in your code?

Filed under: Solid System Design on 2026-01-02 10:24:20

Great — this is the right moment to learn idempotency, because it is one of the pillars of “code that doesn’t break”.

I’ll explain it in three layers:

  1. Theory (mental model)
  2. Database-level design (most important)
  3. Spring Boot practical patterns

No shortcuts, no magic — just solid engineering.

1️⃣ What Does “Idempotent” Mean (Properly)?

An operation is idempotent if executing it once or many times results in the same final state.

Example:

ActionResult
Call oncePayment succeeds
Call twiceStill only one payment
Call 10 timesStill only one payment

Idempotency is not optional for:

  • Payments
  • Orders
  • Account updates
  • Message consumers

2️⃣ The Core Rule (MEMORIZE THIS)

Idempotency must be enforced at the DATABASE level.
Application-only checks are never enough.

Why?

  • Multiple instances
  • Restarts
  • Concurrency
  • Crashes

Only DB sees truth.

3️⃣ Pattern #1 — Idempotency Key (Most Common)

Step 1: Client generates a unique key

Idempotency-Key: 9f2a-88b3-...

Step 2: DB enforces uniqueness

CREATE TABLE processed_requests (
    request_id VARCHAR(50) PRIMARY KEY,
    created_at TIMESTAMP
);

Step 3: Service logic

@Transactional
public void processPayment(String requestId) {

    if (requestRepository.existsById(requestId)) {
        return; // already processed
    }

    requestRepository.save(new ProcessedRequest(requestId));

    // safe business logic
    debit();
    ledger();
}

Why this works

  • Duplicate request → DB prevents double execution
  • Safe under concurrency
  • Works across instances

4️⃣ Pattern #2 — Unique Business Constraint

Used when business naturally defines uniqueness.

Example: One payment per order

UNIQUE (order_id)
@Transactional
public void pay(Long orderId) {
    paymentRepository.save(new Payment(orderId));
}

Second call → DB rejects

5️⃣ Pattern #3 — State Machine (Advanced & Safe)

Only allow valid state transitions.

Example

CREATED → PAID → SETTLED
UPDATE orders
SET status = 'PAID'
WHERE id = :id AND status = 'CREATED';

If update count = 0 → already processed.

6️⃣ Pattern #4 — Message Consumer Idempotency

DB Table

processed_events (
  event_id VARCHAR PRIMARY KEY
)

Consumer Logic

@Transactional
public void consume(Event event) {

    if (eventRepo.exists(event.getId()))
        return;

    eventRepo.save(event.getId());

    process(event);
}

Kafka/RabbitMQ will redeliver — your system stays safe.

7️⃣ What NOT to Do ❌

Wrong ApproachWhy it fails
In-memory flagsFails on restart
Redis-onlyData loss risk
SynchronizedNot distributed
UI preventionBackend retries ignore it

8️⃣ Idempotency + Transactions (Critical)

Correct order:

  1. Insert idempotency record
  2. Perform business logic
  3. Commit transaction

If transaction fails → idempotency record rolls back.

9️⃣ Visual Flow

Request arrives
   ↓
Check idempotency key
   ↓
Already processed? → EXIT
   ↓
Execute logic
   ↓
Commit

? The One-Line Rule

If an operation changes state, it must be idempotent.

? Mini Exercise (Very Important)

Take one method you wrote and answer:

  • What identifies this request uniquely?
  • Where will I store that uniqueness?
  • What happens on retry?

About Author:
N
Neha Sharma     View Profile
Hi, I am using MCQ Buddy. I love to share content on this website.