Go'da idempotent uç noktalar: anahtarlar, çoğaltma önleme tabloları, yeniden denemeler
Go'da idempotans anahtarları, çoğaltma önleme tabloları ve yeniden-denemeye dayanıklı handler'larla ödemeler, içe aktarmalar ve webhook'lar için idempotent uç noktalar tasarlayın.

Yeniden-denemeler neden çoğaltma yaratır (ve idempotans neden önemlidir)
Yeniden-denemeler hiçbir şey "yanlış" değilken bile olur. Bir istemci zaman aşımına uğrar ama sunucu hâlâ çalışıyor olabilir. Mobil bağlantı düşebilir ve uygulama tekrar denemeye koyulur. Bir iş çalıştırıcı 502 alır ve aynı isteği otomatik olarak yeniden gönderir. Kuyruklar ve webhook'larla yaygın olan "en az bir kez teslim" modelinde çoğaltmalar normaldir.
Bu yüzden idempotans önemlidir: tekrarlanan istekler tek bir istek kadar aynı nihai sonuca yol açmalıdır.
Birkaç terim kolayca karışır:
- Güvenli: çağırmak durum değiştirmez (okuma gibi).
- İdempotent: birçok kez çağırmak, bir kez çağırmakla aynı etkiye sahiptir.
- En az bir kez: gönderici "tutunana" kadar yeniden dener, bu yüzden alıcı çoğaltmaları yönetmek zorundadır.
Idempotans yoksa, yeniden-denemeler gerçek hasara yol açabilir. Bir ödeme uç noktası, ilk tahsilat başarılı olsa ama yanıt istemciye ulaşmasa iki kere ücretlendirebilir. Bir içe aktarma uç noktası, bir işçi zaman aşımından sonra yeniden denediğinde tekrar satırlar oluşturabilir. Bir webhook işleyicisi aynı olayı iki kere işleyip iki e-posta gönderebilir.
Ana nokta: idempotans bir API sözleşmesidir, özel bir uygulama detayından ziyade açıkça tanımlanmalıdır. İstemciler neyin yeniden denenebileceğini, hangi anahtarın gönderileceğini ve bir çoğaltma tespit edildiğinde hangi yanıtı bekleyebileceklerini bilmelidir. Davranışı sessizce değiştirirseniz, yeniden-deneme mantığını kırarsınız ve yeni hata modları yaratırsınız.
İdempotans izleme ve mutabakatı değiştirmez. Çoğaltma oranlarını izleyin, "replay" kararlarını kaydedin ve dönemsel olarak harici sistemleri (ör. ödeme sağlayıcısı) veritabanınızla karşılaştırın.
Her uç nokta için idempotans kapsamını ve kurallarını seçin
Tablolar veya ara katmanlar eklemeden önce "aynı istek"in ne anlama geldiğine ve istemci yeniden denediğinde sunucunun ne yapmayı taahhüt edeceğine karar verin.
Çoğu sorun POST'ta çıkar çünkü genellikle bir şey oluşturur veya yan etki tetikler (kartı tahsil etme, mesaj gönderme, içe aktarma başlatma). PATCH de sadece basit bir alan güncellemesi değilse idempotans gerektirebilir. GET durum değiştirmemelidir.
Kapsamı tanımlayın: bir anahtar nerede benzersizdir
İş kurallarınızla eşleşen bir kapsam seçin. Çok geniş seçmek geçerli işleri engeller. Çok dar seçmek çoğaltmalara izin verir.
Yaygın kapsamlar:
- Uç nokta + müşteri başına
- Uç nokta + harici nesne (ör. invoice_id veya order_id)
- Uç nokta + kiracı (multi-tenant sistemler için)
- Uç nokta + ödeme yöntemi + tutar (sadece ürün kurallarınız izin veriyorsa)
Örnek: "Ödeme oluştur" uç noktası için anahtarı müşteri başına benzersiz yapın. "Webhook olayı alma" için ise sağlayıcının sağladığı event ID'yi kapsam olarak kullanın (sağlayıcıdan gelen global benzersizlik).
Çoğaltmada neyi tekrar edeceğinize karar verin
Bir çoğaltma geldiğinde, ilk başarılı denemenin aynı sonucunu döndürün. Pratikte bu, aynı HTTP durum kodunu ve aynı yanıt gövdesini (veya en azından aynı kaynak kimliğini ve durumu) yeniden oynatmak demektir.
İstemciler buna dayanır. İlk deneme başarılı oldu ama ağ koptuysa, yeniden-deneme ikinci bir tahsilat veya ikinci bir içe aktarma işi oluşturmalıdır.
Saklama penceresi seçin
Anahtarlar süresi dolmalı. Gerçekçi yeniden-denemeleri ve gecikmiş işleri kapsayacak kadar saklayın.
- Ödemeler: 24 ila 72 saat yaygındır.
- İçe aktarmalar: kullanıcılar daha sonra yeniden deneyebileceği için bir hafta makul olabilir.
- Webhook'lar: sağlayıcının yeniden-deneme politikasına uymayı hedefleyin.
"Aynı istek"i tanımlama: açık anahtar vs gövde hash'i
Açık bir idempotans anahtarı (başlık veya alan) genellikle en temiz kuraldır.
Gövde hash'i bir geri işlev (backstop) olarak yardımcı olabilir, ama alan sırası, boşluklar, zaman damgaları gibi zararsız değişikliklerle kolayca bozulur. Hash kullanacaksanız, girdi normalizasyonu yapın ve hangi alanların dahil olduğunu katı tutun.
İdempotans anahtarları: pratikte nasıl çalışır
İdempotans anahtarı, istemci ile sunucu arasında basit bir sözleşmedir: "Bu anahtarı tekrar görürseniz, aynı istek olarak işlem yapın." Yeniden-denemeye dayanıklı API'ler için en pratik araçlardan biridir.
Anahtar her iki taraftan da gelebilir, ama çoğu API için istemci tarafından üretilmelidir. İstemci aynı eylemi yeniden denediğini bildiği için aynı anahtarı denemeler arasında tekrar kullanabilir. Sunucu tarafından üretilen anahtarlar, bir "taslak" kaynak (ör. içe aktarma işi) ilk oluşturulurken ve sonrasında istemcinin o iş ID'si ile tekrar denemesine izin verirken yardımcı olur, ama ilk istek için faydası sınırlıdır.
En az 128 bit rastgelelik hedefleyin (ör. 32 hex karakter veya UUID). Anahtarları zaman damgaları veya kullanıcı ID'lerinden oluşturmayın.
Sunucuda, anahtarı kötü kullanımı tespit etmek ve orijinal sonucu yeniden oynatmak için yeterli bağlamla saklayın:
- Çağrıyı yapan (hesap veya kullanıcı ID)
- Hangi uç nokta veya işlem için olduğu
- Önemli istek alanlarının bir hash'i
- Geçerli durum (devam ediyor, başarılı, başarısız)
- Yeniden oynatılacak yanıt (durum kodu ve gövde)
Anahtar tipik olarak kullanıcı (veya API token) + uç nokta bazında kapsamlanmalıdır. Aynı anahtar farklı bir payload ile kullanılırsa, net bir hata ile reddedin. Bu, hatalı bir istemcinin eski bir anahtarı yeni bir ödeme tutarıyla kullanmasının önüne geçer.
Yeniden oynatma durumunda, ilk başarılı denemenin aynı sonucunu döndürün: aynı HTTP durum kodu ve gövdeyi, yeni bir okuma yapıp değişebilecek bir sonucu değil.
PostgreSQL'de dedup tabloları: basit, güvenilir bir desen
Özel bir çoğaltma önleme tablosu idempotans uygulamanın en basit yollarından biridir. İlk istek idempotans anahtarı için bir satır oluşturur. Her yeniden-deneme aynı satırı okur ve saklanan sonucu döndürür.
Ne saklanmalı
Tabloyu küçük ve odaklı tutun. Yaygın bir yapı:
key: idempotans anahtarı (text)owner: anahtarın kime ait olduğu (user_id, account_id veya API client ID)request_hash: önemli istek alanlarının hash'iresponse: nihai yanıt yükü (genellikle JSON) veya saklanan sonuca işaret eden bir göstergecreated_at: anahtarın ilk görüldüğü zaman
Benzersiz kısıtlama bu desenin çekirdeğidir. (owner, key) üzerinde benzersizliği zorlayın ki bir istemci çift oluşturamasın ve iki farklı istemci çakışmasın.
Ayrıca request_hash saklayarak anahtar kötü kullanımını tespit edebilirsiniz. Aynı anahtar ancak farklı hash ile gelirse, iki farklı işlemi karıştırmak yerine hata döndürün.
Saklama ve indeksleme
Dedup satırları sonsuza dek yaşamamalı. Gerçek yeniden-deneme penceresini kapsayacak kadar saklayın, sonra temizleyin.
Yük altında hız için:
- Hızlı ekleme veya sorgu için
(owner, key)üzerinde benzersiz indeks - Temizlemeyi ucuzlaştırmak için
created_atüzerinde opsiyonel indeks
Yanıt büyükse, bir gösterge (ör. sonuç ID'si) saklayın ve tam yükü başka yerde tutun. Bu, tablo şişmesini azaltırken yeniden-deneme davranışını tutarlı kılar.
Adım adım: Go'da yeniden-denemeye dayanıklı bir handler akışı
Yeniden-denemeye dayanıklı bir handler iki şeye ihtiyaç duyar: "aynı isteği tekrar tanımlamanın" kararlı bir yolu ve ilk sonucu saklayıp yeniden oynatacağınız kalıcı bir yer.
Ödemeler, içe aktarmalar ve webhook alımı için pratik bir akış:
-
İsteği doğrulayın; sonra üç değer türetin: idempotans anahtarı (başlıktan veya istemci alanından), bir owner (kiracı veya kullanıcı ID'si) ve bir istek hash'i (önemli alanların hash'i).
-
Bir veritabanı işlemi başlatın ve bir dedup kaydı oluşturmaya çalışın. Bunu
(owner, key)üzerinde benzersiz yapın.request_hash, durum (başladı, tamamlandı) ve yanıt için yer tutucular saklayın. -
Eğer ekleme çakışırsa, mevcut satırı yükleyin. Eğer tamamlandıysa, saklanan yanıtı döndürün. Eğer başlandıysa, kısa bir süre bekleyin (basit polling) veya 409/202 döndürüp istemcinin sonra yeniden denemesini isteyin.
-
Dedup satırını başarıyla "sahiplendiğinizde" iş mantığını yalnızca bir kez çalıştırın. Mümkünse yan etkileri aynı işlem içinde yazın. İş sonucunu ve HTTP yanıtını (durum kodu ve gövde) saklayın.
-
Commit edin ve idempotans anahtarı ile owner'ı loglayın ki destek ekipleri çoğaltmaları izleyebilsin.
Minimal tablo deseni:
create table idempotency_keys (
owner_id text not null,
idem_key text not null,
request_hash text not null,
status text not null,
response_code int,
response_body jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
primary key (owner_id, idem_key)
);
Örnek: "Payout oluştur" uç noktası tahsilattan sonra zaman aşımına uğruyor. İstemci aynı anahtar ile yeniden dener. Handler çakışma yoluna girer, tamamlanmış bir kayıt görür ve yeni bir tahsilat yapmadan önceki payout ID'sini döndürür.
Ödemeler: zaman aşımı olsa bile yalnızca bir kez tahsil edin
Ödemeler idempotansın zorunlu olduğu yerdir. Ağlar başarısız olur, mobil uygulamalar yeniden dener ve gateway'ler bazen zaten ürettikleri tahsilat sonrası zaman aşımına düşer.
Pratik kural: idempotans anahtarı tahsilat oluşturmayı korur ve ödeme sağlayıcı kimliği (charge/intent ID) daha sonra tek kaynak olarak kabul edilir. Sağlayıcı ID'sini sakladıktan sonra aynı istek için yeni tahsilat oluşturmayın.
Yeniden-denemeleri ve gateway belirsizliğini yöneten bir desen:
- Idempotans anahtarını okuyun ve doğrulayın.
- Bir veritabanı işlemi içinde
(merchant_id, idempotency_key)ile anahtar bazlı bir ödeme satırı oluşturun veya alın. Eğerprovider_idzaten varsa, kaydedilmiş sonucu döndürün. provider_idyoksa gateway'e PaymentIntent/Charge yaratması için çağrı yapın.- Gateway başarılı olursa,
provider_id'yi saklayın ve ödemeyi "başarılı" (veya "action gerekiyor") olarak işaretleyin. - Gateway zaman aşımına uğrar veya bilinmeyen bir sonuç dönerse, durumu "beklemede" olarak saklayın ve istemciye yeniden denemesi güvenli olduğu bilgisi veren tutarlı bir yanıt döndürün.
Zaman aşımına nasıl davrandığınız ana detaydır: başarısız olduğunu varsaymayın. Ödemeyi beklemede işaretleyin, sonra sağlayıcıyı sorgulayarak (veya bir webhook ile) doğrulayın.
Hata yanıtları tahmin edilebilir olmalı. İstemciler döndürdüğünüz şemaya göre yeniden-deneme mantığı kurar, bu yüzden durum kodları ve hata şekillerini sabit tutun.
İçe aktarmalar ve toplu uç noktalar: ilerlemeyi kaybetmeden çoğaltmayı önleyin
İçe aktarmalarda çoğaltmalar en çok zarar verir. Kullanıcı bir CSV yükler, sunucu %95'te zaman aşımına uğrar ve kullanıcı yeniden dener. Plan yoksa ya çift satırlar oluşturursunuz ya da kullanıcıya baştan başlamasını söylersiniz.
Toplu işler için iki katmanda düşünün: içe aktarma işi ve içindeki öğeler. İş düzeyinde idempotans aynı isteğin birden çok iş oluşturmasını engeller. Öğe düzeyinde idempotans aynı satırın iki defa uygulanmasını engeller.
İş düzeyinde desen, içe aktarma isteği başına bir idempotans anahtarı gerektirmektir (veya kullanıcı ID'si ile birlikte sabit bir istek hash'inden türetin). Bunu import_job kaydı ile saklayın ve yeniden-denemelerde aynı iş ID'sini döndürün. Handler "Bu işi gördüm, işte güncel durumu" diyebilmeli, "tekrar başlat" dememelidir.
Öğe düzeyinde çoğaltma için veride zaten var olan doğal bir anahtara güvenin. Örneğin her satır bir external_id içerebilir veya (account_id, email) gibi sabit bir kombinasyon olabilir. PostgreSQL'de benzersiz kısıtlama uygulayın ve upsert davranışı kullanın ki yeniden-denemeler çift oluşturmasın.
Yeniden oynatma bir satır zaten varsa ne yapar kararını önceden verin: atla, belirli alanları güncelle, ya da hata ver. "Birleştir" (merge) kullanmaktan kaçının ya da çok net kurallarınız olsun.
Kısmi başarı normaldir. Tek bir büyük "tamam" veya "başarısız" döndürmek yerine, satır bazlı sonuçları iş ile ilişkilendirerek saklayın: satır numarası, doğal anahtar, durum (oluşturuldu, güncellendi, atlandı, hata) ve hata mesajı. Yeniden-denemede, zaten tamamlanmış satırlar için aynı sonuçları koruyarak güvenle tekrar çalıştırabilirsiniz.
İçe aktarmaları yeniden başlatılabilir yapmak için kontrol noktaları (checkpoint) ekleyin. Sayfalara ayırın (ör. her seferinde 500 satır), son işlenmiş imleci (satır indeksi veya kaynak imleci) saklayın ve her sayfa commit edildikten sonra güncelleyin. İş çökerse, bir sonraki deneme son kontrol noktasından devam eder.
Webhook alımı: çoğalt, doğrula, sonra güvenli şekilde işle
Webhook gönderenler yeniden dener. Olayları sıra dışı gönderebilirler. Handler her teslimatta durumu güncellerse, sonunda kaydı iki kere oluşturur, iki kere e-posta gönderir veya iki kere tahsilat yapar.
Önce en iyi çoğaltma anahtarını seçin. Sağlayıcı bir benzersiz event ID veriyorsa, bunu kullanın. Sağlayıcı event ID yoksa gövde hash'ine geri düşün.
Güvenlik önce gelir: imzayı kabul etmeden doğrulayın. İmza başarısızsa isteği reddedin ve dedup kaydı yazmayın. Aksi halde bir saldırgan bir event ID "rezerve" edip gerçek olayları engelleyebilir.
Yeniden-denemeler altında güvenli bir akış:
- İmzayı ve temel biçimi doğrulayın (gerekli başlıklar, event ID).
- Event ID'yi benzersiz kısıtlama ile bir dedup tablosuna ekleyin.
- Eğer ekleme çoğaltma nedeniyle başarısız olursa, hemen 200 döndürün.
- Denetim ve hata ayıklama için ham yükü (ve başlıkları) saklayın.
- İşlemeyi kuyruğa ekleyin ve çabuk 200 döndürün.
Hızlı onaylamak önemlidir çünkü birçok sağlayıcının kısa zaman aşımı vardır. İstek içinde en küçük güvenilir işi yapın: doğrulama, dedup, saklama. Sonra asenkron işle (işçi, kuyruk, arka plan işi). Asenkron yapamıyorsanız, dahili yan etkileri aynı event ID'ye anahtarlanmış tutarak işlemeyi idempotent yapın.
Sıra dışı teslimat normaldir. "created" olayının "updated"'den önce geldiğini varsaymayın. Harici nesne ID'si ile upsert tercih edin ve son işlenen olay zaman damgası veya versiyonu tutun.
Ham yükleri saklamak, müşteri "güncelleme almadık" dediğinde yardımcı olur. Hata düzeltip yeniden işlemek için sağlayıcıdan yeniden istemenize gerek kalmadan saklanan gövdeden yeniden çalıştırabilirsiniz.
Eşzamanlılık: paralel istekler altında doğru kalmak
Aynı idempotans anahtarıyla iki istek aynı anda geldiğinde işler karışır. Eğer her iki handler da sonucu kaydetmeden önce "işi yap" adımını çalıştırırsa, yine çift tahsilat, çift içe aktarma veya iki iş kuyruğa ekleme olabilir.
En basit koordinasyon noktası veritabanı işlemidir. İlk adımı "anahtarı talep et" yapın ve kimin kazandığını veritabanına bırakın. Yaygın seçenekler:
- Dedup tablosuna benzersiz insert (veritabanı bir kazanan belirler)
- Dedup satırını oluşturduktan sonra
SELECT ... FOR UPDATE - Idempotans anahtarının hash'i ile işlem düzeyinde advisory lock
- Son bir güvenlik hattı olarak iş kaydı üzerinde benzersiz kısıtlama
Uzun süren işler için dış sistemleri çağırırken satır kilidi tutmaktan kaçının. Bunun yerine dedup satırında küçük bir durum makinesi saklayın ki diğer istekler hızlıca çıkış yapsın.
Pratik durum seti:
in_progressvestarted_atcompletedve önbelleğe alınmış yanıtfailedve bir hata kodu (opsiyonel, yeniden-deneme politikanıza bağlı)expires_at(temizlik için)
Örnek: iki uygulama örneği aynı ödeme isteğini alır. A örneği anahtarı ekler ve in_progress yapar, sonra sağlayıcıyı çağırır. B örneği çakışma yoluna girer, dedup satırını okur, in_progress görür ve hızlı bir "işlem devam ediyor" yanıtı döner (veya kısa bekleyip tekrar kontrol eder). A bitirdiğinde satırı completed yapar ve yanıt gövdesini saklar; sonraki yeniden-denemeler tam olarak aynı çıktıyı alır.
İdempotansı bozan yaygın hatalar
Çoğu idempotans hatası karmaşık kilitleme değil, "neredeyse doğru" seçimlerin yeniden-denemeler, zaman aşımı veya iki kullanıcının benzer eylemleri altında başarısız olmasıdır.
Yaygın bir tuzak, idempotans anahtarını küresel olarak benzersiz saymaktır. Anahtarı scope etmezseniz (kullanıcı, hesap veya uç nokta ile), iki farklı istemci çakışıp birbirlerinin sonucunu alabilir.
Diğer bir sorun, aynı anahtar aynı zamanda farklı istek gövdesi ile kabul edilmesidir. İlk çağrı $10 içindi, tekrar $100 ise ilk sonucu sessizce döndürmemelisiniz. Bir istek hash'i saklayın, tekrar kontrol edin ve uyuşmazlığı açık bir çakışma hatasıyla reddedin.
İstemciler ayrıca yeniden oynatıldığında farklı yanıt şekli veya durum kodu alınca karışır. İlk çağrı 201 ve JSON gövde döndürdüyse, yeniden-deneme aynı gövdeyi ve tutarlı bir durum kodunu almalı. Yeniden oynatma davranışını değiştirmek istemcilerin tahmin yürütmesine yol açar.
Sık hata nedenleri:
- Yeniden başlatmada dedup durumunu kaybeden yalnızca bellek içi bir harita veya cache'e güvenmek.
- Anahtarı scope etmemek (kullanıcılar arası veya uç nokta arası çakışmalar).
- Aynı anahtar için payload uyuşmazlığını doğrulamamak.
- Yan etkiyi önce yapmak (tahsilat, insert, publish) ve dedup kaydını sonra yazmak.
- Her yeniden-denemede yeni bir oluşturulan ID döndürmek yerine orijinal sonucu yeniden oynatmamak.
Bir cache okuma hızlandırabilir, ama doğruluk kaynağı kalıcı olmalı (genellikle PostgreSQL). Aksi halde dağıtımdan sonra yapılan yeniden-denemelerde çoğaltma oluşabilir.
Ayrıca temizlik planlayın. Her anahtarı sonsuza dek saklarsanız tablolar büyür ve indeksler yavaşlar. Gerçek yeniden-deneme davranışına göre saklama penceresi belirleyin, eski satırları silin ve benzersiz indeksin küçük kalmasına dikkat edin.
Hızlı kontrol listesi ve sonraki adımlar
Idempotansı API sözleşmenizin bir parçası olarak ele alın. İstemci, kuyruk veya gateway tarafından yeniden denenebilecek her uç nokta için "aynı istek"in ne anlama geldiği ve "aynı sonuç"un nasıl göründüğü açıkça tanımlanmalıdır.
Yayımlamadan önce kontrol listesi:
- Her yeniden-denenebilir uç nokta için idempotans kapsamı tanımlandı mı (kullanıcı, hesap, sipariş, harici olay bazında) ve yazılı mı?
- Çoğaltma, yalnızca kodda kontrol edilmek yerine veritabanı tarafından mı zorlanıyor (idempotans anahtarı ve kapsam üzerinde benzersiz kısıtlama)?
- Yeniden oynatma yapıldığında aynı durum kodunu ve yanıt gövdesini (veya belgelenmiş kararlı bir alt kümesini) döndürüyor musunuz, yeni bir nesne veya yeni zaman damgası yerine?
- Ödemeler için, gönderim sonrası bilinmeyen sonuçları güvenli şekilde yönetiyor musunuz (submit sonrası zaman aşımı, gateway "processing" diyor) ve iki kez tahsilat olmuyor mu?
- Loglar ve metrikler, bir isteğin ilk kez görüldüğünü mü yoksa yeniden oynatıldığını mı açıkça gösteriyor?
Eğer herhangi bir madde "muhtemelen" ise, şimdi düzeltin. Çoğu hata stres altında ortaya çıkar: paralel yeniden-denemeler, yavaş ağlar ve kısmi kesintiler.
Eğer AppMaster (appmaster.io) üzerinde dahili araçlar veya müşteri odaklı uygulamalar inşa ediyorsanız, idempotans anahtarlarını ve PostgreSQL dedup tablosunu erken tasarlamak yardımcı olur. Böylece platform gereksinimler değiştikçe Go backend kodu yeniden üretilse bile yeniden-deneme davranışınız tutarlı kalır.
SSS
Yeniden-denemeler, ağlar ve istemciler günlük kusurlar gösterdiği için normaldir. Bir istek sunucuda başarıyla işlenmiş olabilir ancak yanıt istemciye ulaşmayabilir; istemci tekrar gönderince sunucu aynı işi ikinci kez yapar. Sunucu ilk sonucu tanıyıp yeniden oynatmıyorsa bu durum çift ücretlendirme veya çift kayıt gibi sorunlara yol açar.
Aynı eylemin her yeniden-denemesinde aynı anahtarı gönderin. Anahtarı istemci üretmeli; rastgele, tahmin edilemez bir dize (örneğin UUID) kullanın ve aynı anahtarı farklı bir işlem için yeniden kullanmayın.
İş kurallarınıza uygun şekilde kapsamlayın: genellikle uç nokta + çağıran kimliği (kullanıcı, hesap, kiracı veya API token). Bu, iki farklı müşterinin aynı anahtarla çakışmasını ve birbirlerinin sonucunu almasını önler.
İlk başarılı denemenin aynı sonucunu döndürün. Pratikte, aynı HTTP durum kodunu ve aynı yanıt gövdesini (veya en azından aynı kaynak kimliğini ve durumu) yeniden oynatın, böylece istemci güvenle yeniden deneyebilir ve ikinci bir yan etki oluşmaz.
Açık bir çakışma hatasıyla reddedin, tahmin yapmayın. Önemli isteğe alanlarının bir hash'ini saklayın ve aynı anahtarla gelen farklı bir yük varsa işlemi karıştırmamak için hızlıca hata verin.
Anahtarları gerçekçi yeniden-deneme sürelerini kapsayacak kadar saklayın, sonra temizleyin. Örnek varsayılanlar: ödemeler için 24–72 saat, içe aktarmalar için bir hafta; webhook'lar için sağlayıcının yeniden-deneme politikasına uyun.
Adana özel bir çoğaltma önleme tablosu işe yarar çünkü veritabanı benzersiz kısıtlamayı zorlayabilir ve yeniden başlatmalarda kalıcı olur. Sahip kapsamı, anahtar, istek hash'i, durum ve yeniden oynatılacak yanıtı saklayın; (owner, key) üzerinde benzersiz kısıtlama uygulayın.
Önce anahtarı veritabanı işlemi içinde talep edin, sonra yan etkiyi sadece anahtarı başarıyla talep ettiyseniz yapın. Paralel gelen diğer istek benzersiz kısıtla çarpışır, in_progress veya completed görüp bekleme/yeniden deneme yanıtı döner ve mantığın iki kez çalışmasını önlersiniz.
Zaman aşımını "başarısız" saymayın, "bilinmeyen" olarak işaretleyin. Sağlayıcı kimliğiniz (provider ID) varsa bunu kaynak kabul edin; böylece yeniden-denemeler aynı ödeme sonucunu döner ve yeni bir ücret oluşturulmaz.
İki katmanda çoğaltmayı önleyin: iş düzeyinde ve öğe düzeyinde. Yeniden-denemeler aynı içe aktarma iş kimliğini döndürmeli; satırlar için doğal bir anahtar (ör. external_id veya (account_id, email)) kullanıp benzersiz kısıtlama veya upsert ile tekrar işlemekte çoğaltma oluşmasını engelleyin.


