DEBI PRAHARADIKA
← Back to Blog Index
Design Pattern2026-10-183 min read

Idempotency Pattern Yang Sudah Kita Kenal

Idempotency sudah sering kita dengar di dunia perangkat lunak terutama berhubungan dengana sistem pembayaran online. Bagaimana bentuknya, saya akan sedikit menceritakannya disini.

Sampai saat tulisan ini ditulis, saya hanya mengetahui ada 8 pattern, dan mungkin pembaca bisa jauh mengetahui lebih banyak jika bertanya kepada AI. Dan pattern yang saya tuliskan disini beberapa sudah saya pakai di dunia pengembangan software atau aplikasi web.

Sederhananya, Idempotency adalah sifat sesuatu ketika dijalankan 1 atau 10 kali maka hasil akhirnya akan tetap sama dan tidak menimbulkan efek berulang. Contoh di dunia nyata, tombol naik pada lift mall, ketika kita tekan berulang kali maka lift akan tetap naik satu kali, dan inilah contoh nyata idempotency. Contoh di dunia perangkat lunak, ketika menekan tombol Bayar pada eccommerce sebanyak 3 kali maka yang diproses hanya 1 kali pembayaran, dan saldo hanya terpotong 1 kali bukan 3 kali. Contoh pada HTTP method, idempotency dapat ditemui pada method GET, PUT dan DELETE, namun tidak pada method POST.

Dalam sistem modern online, idempotency sangat penting untuk memastikan sistem aman dari data duplikat atau double charge, apalagi pada arsitektur terdistribusi dan internet yang rawan timeout atau network glitch.

Berikut adalah beberapa idempotency pattern yang sudah pernah saya temui dan gunakan, dan mungkin bisa bermanfaat untuk catatan saya ketika lupa sehingga saya buat sesingkat mungkin. Jika pembaca ingin tahu lebih detail bisa menanyakan ke AI asisten kesayangan pembaca.

1. Idempotency Key Pattern / Client-Generated Key

Idempotency Key Pattern

Konsep: Client melakukan generate unique key sebelum request, biasanya menggunakan UUID atau unik lainnya dan kemudian kirim di header. Server menyimpan key ini, jika ada request yang sama masuk lagi dengan key sama, maka langsung return response yang sudah tersimpan tanpa memproses ulang request.

Contoh Implementasi di Stripe API:

curl https://api.stripe.com/v1/charges \
  -H "Idempotency-Key: a1b2c3d4-payment-order-12345" \
  -d amount=2000 -d currency=usd

Stripe menyimpan idempotency key selama 24 jam. Jika request yang sama dengan key sama dikirim ulang dalam jendela waktu itu, misal karena timeout jaringan lalu client retry otomatis, Stripe tidak charge kartu dua kali, cukup return response charge yang pertama.

Contoh Implementasi di PayPal API:

PayPal-Request-Id: 7b8c9d10-order-98765

Sama persis konsepnya dengan Stripe, dipakai di Orders API PayPal untuk mencegah duplicate order creation.


2. Idempotency via Unique Constraint di Database

Database Unique Constraint Idempotency

Konsep: Tidak menyimpan key terpisah, tetapi memanfaatkan unique constraint di kolom database agar insert kedua otomatis gagal dan tidak diproses ulang.

Contoh Implementasi di Shopify Webhooks: Shopify mengirim header X-Shopify-Webhook-Id unik per event. App Merchant biasanya membuat tabel dengan unique constraint di kolom ini:

CREATE TABLE processed_webhooks (
    webhook_id VARCHAR(255) UNIQUE NOT NULL,
    processed_at TIMESTAMP
);

Kalau ada webhook yang sama di-retry Shopify (misal mereka retry sampai 19 kali dalam periode tertentu jika endpoint merchant gagal respon), insert kedua akan gagal karena constraint violation, yaitu sebagai sinyal bahwa event ini sudah pernah diproses.


3. Optimistic Locking / Conditional Write (Compare-and-Swap)

Optimistic Locking dan Conditional Write CAS

Konsep: Update hanya berhasil jika state saat ini sesuai ekspektasi bisa versioning atau kondisi tertentu, jika sudah berubah karena request lain maka operasi otomatis gagal.

Contoh Implementasi di AWS DynamoDB Conditional Writes:

dynamodb.update_item(
    Key={'order_id': 'ORD-123'},
    UpdateExpression='SET #status = :new_status',
    ConditionExpression='#status = :expected_status',
    ExpressionAttributeValues={
        ':new_status': 'SHIPPED',
        ':expected_status': 'PROCESSING'
    }
)

AWS sendiri secara resmi merekomendasikan pattern ini di dokumentasinya untuk mencegah double processing pada distributed system.

Contoh Implementasi Optimistic Locking di JPA/Hibernate:

@Version
private Long version;

Dipakai luas di sistem banking/e-commerce Java-based — setiap update, Hibernate otomatis cek version field, jika sudah berubah sejak dibaca, OptimisticLockException dilempar.


4. Deduplication Table / Event Log Pattern

Deduplication Table dan Event Log Pattern

Konsep: Setiap event masuk akan dicatat di tabel log terpisah sebelum diproses. Sebelum memproses, sistem akan cek terlebih dahulu apakah event ID sudah ada di log.

Contoh Implementasi di Apache Kafka Exactly-Once Semantics (EOS): Kafka sejak versi 0.11 sudah mengimplementasi idempotent producer, dimana tiap producer mendapatkan unique Producer ID (PID), tiap message mendapatkan sequence number. Broker Kafka otomatis reject message dengan sequence number yang sudah pernah diterima dari PID yang sama:

enable.idempotence=true

Ini adalah fitur bawaan Kafka yang dipakai di infrastruktur streaming skala besar.


5. Natural Idempotent Operations (HTTP Method Semantics)

Perbandingan Natural Idempotent vs Non-Idempotent HTTP Operations

Konsep: Beberapa operasi secara alami idempotent jika didesain dengan benar, tanpa perlu mekanisme tambahan.

Contoh Implementasi nyata di RESTful API Design (Stripe, GitHub API, dll):

PUT /users/123 { "name": "Debi" }   ← idempotent secara natural
                                        (set nilai final, bukan increment)

POST /users/123/credit { "amount": 100 }  ← TIDAK idempotent
                                              (kalau di-retry, credit nambah 2x)

GitHub API secara eksplisit mendokumentasikan bahwa PUT dan DELETE method mereka idempotent by design, retry aman tanpa efek samping tambahan.


6. Token Bucket / Single-Use Token Pattern

Alur Autentikasi Single-Use Token Idempotency

Konsep: Server menghasilkan token sekali pakai, dengan ditandai "used" setelah dikonsumsi, request kedua dengan token yang sama akan otomatis ditolak.

Contoh Implementasi di Google OAuth Authorization Code: Authorization code di OAuth 2.0 flow Google hanya bisa ditukar sekali menjadi access token — kalau ada percobaan tukar kedua dengan code yang sama, Google API akan return error invalid_grant. Ini mencegah replay attack sekaligus menjamin idempotency di proses exchange token.


7. Idempotent Consumer Pattern (Message Queue Processing)

Idempotent Consumer Pattern Message Queue

Konsep: Consumer di message queue architecture mencatat message ID yang sudah diproses, skip kalau message yang sama datang lagi.

Contoh Implementasi di Netflix (dari blog engineering mereka): Netflix mendokumentasikan penggunaan pattern idempotent consumer di sistem billing mereka — karena Kafka dan SQS mereka pakai model at-least-once delivery (bukan exactly-once end-to-end), consumer wajib self-dedupe berdasarkan event ID yang tersimpan di database sebelum benar-benar eksekusi efek samping (charge kartu, kirim email, dll).


8. Distributed Lock Pattern

Distributed Lock Concurrency Mutex

Konsep: Sebelum mengeksekusi operasi kritis, maka ambil lock terlebih dahulu biasanya via Redis, Zookeeper, dll — jika lock gagal diambil, maka request kedua ditolak/ditunda.

Contoh Implementasi di Redlock Algorithm:

import redis
lock = redis_client.set('order:12345:lock', 'locked', nx=True, ex=30)
if lock:
    process_payment()
    redis_client.delete('order:12345:lock')

Dipakai luas di sistem e-commerce untuk mencegah double-processing saat dua worker mencoba proses order yang sama bersamaan.


Ringkasan Tabel

Pattern Contoh Real Kapan Dipakai
Idempotency Key (client-generated) Stripe, PayPal Payment API, mutasi finansial
Unique DB Constraint Shopify Webhooks Webhook processing, event ingestion
Optimistic Locking/Conditional Write AWS DynamoDB, Hibernate State transition (order status, dll)
Dedup Table/Event Log Kafka EOS, AWS SQS FIFO Message queue processing
Natural Idempotent HTTP GitHub API, Stripe REST Desain API secara umum
Single-Use Token Google OAuth Auth flow, sensitive one-time action
Idempotent Consumer Netflix billing Consumer di distributed system
Distributed Lock Redis Redlock Concurrency control lintas worker/instance