Delivery semantics & idempotency

Handling network retries without charging a customer twice.

The idea

Networks are unreliable. If you send a "Charge $50" message and don't get an ACK, you must retry (At-Least-Once Delivery). But what if the first message did process, and only the ACK was lost? You just charged them $100!

To achieve Exactly-Once Processing, the operation must be Idempotent (safe to run multiple times). We do this by attaching a unique Idempotency Key to the request. The receiver checks a ledger: if it has seen this key before, it skips the work and just returns "Success".

Client Payment API Idempotency Keys User Balance: $100
Ready to send.

How it works (Idempotency)

def charge_user(user_id, amount, idempotency_key):
    # 1. Check if we've already done this
    if db.has_key(idempotency_key):
        return "Success (Deduped)"
        
    # 2. Begin Transaction
    db.begin()
    db.deduct_balance(user_id, amount)
    
    # 3. Save the key in the SAME transaction!
    db.save_key(idempotency_key)
    db.commit()
    
    return "Success (Processed)"