Skip to content
advanced Phase 86 · Distributed Advanced

Idempotency

Idempotent operations, duplicate detection, and idempotency keys for reliable systems

45m
0 problems
Topic Progress 0%

Idempotent Operations

Idempotency Concept

Idempotent: Same operation = same result

Non-idempotent:
  POST /orders → creates order (each call = new order)

Idempotent:
  PUT /orders/123 → updates order (same result every time)

HTTP Methods

Method    | Idempotent | Safe | Use Case
──────────|────────────|──────|──────────────────
GET       | Yes        | Yes  | Read data
PUT       | Yes        | No   | Update resource
DELETE    | Yes        | No   | Remove resource
PATCH     | No         | No   | Partial update
POST      | No         | No   | Create resource

Magento Idempotent Examples

// Idempotent: set inventory to specific value
$inventory->setStock(100); // Same result every time

// Non-idempotent: increment inventory
$inventory->increment(5); // Different result each time

// Make increment idempotent with versioning
$inventory->setStock(100, $expectedVersion);
// Only succeeds if version matches

Idempotency Keys

Key Generation

// Generate idempotency key from request
$key = hash('sha256', json_encode([
    'user_id' => $userId,
    'action' => 'place_order',
    'cart_id' => $cartId,
    'timestamp' => $request->getHeader('X-Idempotency-Key')
]));

Key Storage and Check

function processWithIdempotency($key, $operation) {
    // Check if already processed
    $existing = $this->idempotencyStore->get($key);
    if ($existing) {
        return $existing; // Return cached result
    }
    
    // Process operation
    $result = $operation();
    
    // Store result with TTL
    $this->idempotencyStore->set($key, $result, 86400);
    
    return $result;
}

API Idempotency Header

// Client sends idempotency key
$clientIdempotencyKey = $request->getHeader('X-Idempotency-Key');

// Server checks and processes
if ($this->idempotencyStore->exists($clientIdempotencyKey)) {
    return $this->idempotencyStore->get($clientIdempotencyKey);
}

$result = $this->processRequest($request);
$this->idempotencyStore->set($clientIdempotencyKey, $result);
return $result;

Duplicate Detection

Detection Strategies

1. Idempotency keys (explicit)
2. Unique constraints (database)
3. Deduplication windows (time-based)
4. Content hashing (hash matching)

Database Unique Constraints

-- Prevent duplicate orders
ALTER TABLE sales_order 
ADD UNIQUE KEY unique_client_order (client_order_id);

-- Prevent duplicate payments
ALTER TABLE payment_transaction 
ADD UNIQUE KEY unique_txn (transaction_id, gateway);

Time-Window Deduplication

function isDuplicate($messageId, $windowSeconds = 300) {
    $key = 'dedup_' . $messageId;
    
    // SET NX = set if not exists, EX = expiry
    $result = $this->redis->set($key, '1', ['NX', 'EX' => $windowSeconds]);
    
    return $result === false; // false = already exists = duplicate
}

// Usage
if ($this->isDuplicate($message->getId())) {
    $this->logger->info('Duplicate message ignored', [
        'message_id' => $message->getId()
    ]);
    return;
}
$this->processMessage($message);

Idempotent Design Patterns

PUT for Updates

// Idempotent: PUT replaces entire resource
PUT /api/orders/123
{
    "status": "shipped",
    "tracking": "12345"
}
// Same result on every call

Conditional Updates

// Optimistic locking for idempotency
function updateOrder($orderId, $data, $expectedVersion) {
    $result = $this->db->update('sales_order', $data, [
        'entity_id = ?' => $orderId,
        'version = ?' => $expectedVersion
    ]);
    
    if ($result === 0) {
        throw new ConflictException('Version mismatch');
    }
    return $result;
}

Idempotent Queue Processing

function processMessage($message) {
    $messageId = $message->getId();
    
    // Check deduplication
    if ($this->isDuplicate($messageId)) {
        return;
    }
    
    // Process with idempotency key
    $this->processWithIdempotency($messageId, function () use ($message) {
        return $this->handleMessage($message);
    });
    
    // Acknowledge
    $message->ack();
}

Quiz

1. What is an idempotent operation?

Question 1 options

2. What is an idempotency key?

Question 2 options

3. Which HTTP method is idempotent?

Question 3 options

Flashcards

Question

Idempotent operation?

Answer

Same operation produces same result every time

Question

Idempotency key?

Answer

Unique identifier to detect and handle duplicate requests

Question

Duplicate detection strategies?

Answer

Idempotency keys, unique constraints, time windows, content hashing

Question

Idempotent HTTP methods?

Answer

GET, PUT, DELETE are idempotent; POST and PATCH are not

Revision Notes

Key Takeaways

  • 1. Idempotent operations produce same result on repeat execution
  • 2. Idempotency keys uniquely identify requests for deduplication
  • 3. Database unique constraints prevent duplicate records
  • 4. Time-window deduplication ignores messages within TTL
  • 5. PUT and DELETE are naturally idempotent HTTP methods

Interview Tips

  • Explain idempotency and why it matters for distributed systems
  • Discuss idempotency key generation and storage strategies
  • Compare different duplicate detection approaches

Cheat Sheet

Idempotency:
  Same operation = same result
  GET, PUT, DELETE are idempotent
  POST, PATCH are not

Idempotency Keys:
  Unique per request
  Store with TTL (24h)
  Check before processing

Duplicate Detection:
  1. Idempotency keys (explicit)
  2. Unique constraints (DB)
  3. Time windows (Redis NX)
  4. Content hashing