Yazılım

Idempotency Nedir? API'lerde Aynı İsteğin İki Kez İşlenmesini Önleme

Talha Aslan 16 dakikalık okuma 2 görüntülenme

Idempotency nedir?

Idempotency, bir işlemi bir kez de çalıştırsanız birçok kez de çalıştırsanız sistemin son durumunun aynı kalması özelliğidir. API dünyasında bu, ağ hatası yüzünden tekrar gönderilen bir isteğin ikinci bir sipariş, ikinci bir tahsilat ya da ikinci bir kayıt üretmemesi anlamına gelir.

Kısacası idempotency, tekrarın zararsız olmasıdır. İnternet bağlantıları kesilir, yanıtlar kaybolur ve istemciler pes etmeden yeniden dener. Bu yüzden güvenilir bir API, aynı isteğin iki kez gelebileceğini baştan varsayar.

Bu yazıda terimi kavram düzeyinde anlatıyoruz. Kod bloğu yok; yalnızca mantığı, kullanım alanlarını ve sınırlarını göreceksiniz.

Asansör düğmesi örneğiyle idempotency nedir?

Bir asansörün üçüncü kat düğmesine bir kez bastığınızı düşünün. Asansör üçüncü kata gider. Sabırsızlanıp düğmeye beş kez daha basarsanız ne değişir? Hiçbir şey. Asansör yine tek bir kata gidiyor ve sonuç aynı kalıyor. İşte bu düğme idempotenttir.

Şimdi bir gazete bayisine "bir gazete ver" dediğinizi düşünün. Bayi duymadığınızı sanıp aynı siparişi iki kez verirseniz iki gazete alırsınız. Bu işlem idempotent değildir, çünkü her tekrar sonucu değiştirir.

Yazılımda fark tam olarak bu ikisi arasındadır. "Siparişin durumunu onaylandı yap" komutu asansör düğmesine benzer. "Sepete bir ürün ekle" komutu ise gazete siparişine benzer. Ancak ikinciyi de doğru tasarımla asansör düğmesine çevirebilirsiniz; bunu ilerleyen bölümlerde göreceksiniz.

Matematikten gelen kökeni de bu benzetmeyi destekler. Matematikte bir fonksiyonu art arda uygulamanın tek uygulamadan farkı yoksa o fonksiyon idempotenttir. Mutlak değer almak buna örnektir: eksi üçün mutlak değerini bir kez de on kez de alsanız üç bulursunuz. Yazılımdaki idempotency nedir sorusunun cevabı da aynı mantığa dayanır: işlemi tekrar uygulamak sonucu bozmaz.

Çift tahsilat sorunu neden ortaya çıkar?

Sorunun kökü, istemcinin sunucudan gelen yanıtı göremediği anlardır. Müşteri "Öde" düğmesine basar. Sunucu ödemeyi alır ve işler. Ama yanıt yolda kaybolur ya da zaman aşımı süresi dolar. İstemci başarısız olduğunu sanır.

Bu noktada üç olası davranış vardır:

  • Uygulama isteği otomatik olarak yeniden gönderir.
  • Müşteri sayfayı yeniler veya düğmeye ikinci kez basar.
  • Aradaki bir ağ geçidi veya yük dengeleyici isteği kendi kendine tekrar eder.

Her üç durumda sunucu aynı isteği ikinci kez görür. Sunucu bunun bir tekrar olduğunu bilmiyorsa müşteriden iki kez para çeker. Dolayısıyla çift tahsilat çoğu zaman bir hata değil, tasarımdaki bir boşluğun doğal sonucudur.

Sunucu tarafındaki hata sayfaları da benzer durumlar yaratır. Örneğin 502 Bad Gateway hatası alan bir istemci, işlemin gerçekten gerçekleşip gerçekleşmediğini bilemez.

Bu durumun tehlikesi, hatanın kimseye görünmemesidir. Müşteri bir ödeme görür, sunucu iki ödeme görür. Fark ancak ay sonu mutabakatında ya da müşterinin şikayetinde ortaya çıkar. Yani sorun büyür, ama kimse uyarılmaz.

HTTP yöntemlerinden hangileri idempotenttir?

HTTP standardı bu konuda net bir çerçeve çizer. IETF RFC 9110, bir yöntemi şöyle tanımlar: aynı isteğin birçok kez gönderilmesinin etkisi, tek bir istekle aynıdır. Standarda göre GET, HEAD, OPTIONS ve TRACE ile PUT ve DELETE idempotenttir. POST ve PATCH ise tanım gereği idempotent sayılmaz.

Burada önemli bir ayrıntı var. Standart "amaçlanan etkiden" söz eder. Yani kayıt dosyasına yazılan satır sayısı ya da ikinci DELETE isteğinin dönüş kodu aynı olmak zorunda değildir. Örneğin ilk DELETE kaydı siler, ikincisi "bulunamadı" yanıtı verebilir. Sunucudaki son durum ise iki durumda da aynıdır: kayıt yok.

Standart ayrıca yeniden deneme konusunda yol gösterir. İstemci, bağlantı koptuğunda idempotent bir yöntemi otomatik olarak yeniden gönderebilir. İdempotent olmayan bir isteği ise, anlamının gerçekten idempotent olduğunu bilmeden otomatik tekrarlamamalıdır. Ayrıntılar için RFC 9110 idempotent yöntemler bölümüne bakabilirsiniz.

Pratikte bu bilgi iki yerde işinize yarar. Birincisi, yeni bir uç nokta tasarlarken doğru yöntemi seçmenizdir. İkincisi, hangi isteklerin otomatik olarak tekrar denenebileceğini belirlemenizdir. Tarayıcılar, ağ geçitleri ve istemci kütüphaneleri çoğu zaman bu ayrıma göre davranır; dolayısıyla yöntemi yanlış seçmek, istemediğiniz yerde otomatik tekrar tetikleyebilir.

REST tasarımında PUT, PATCH ve POST için idempotency nedir?

REST tarzı API'lerde en sık karıştırılan üçlü bu yöntemlerdir. PUT, bir kaynağı verdiğiniz içerikle tamamen değiştirmek için kullanılır. Aynı PUT'u beş kez göndermek, kaynağı beş kez aynı hale getirir; dolayısıyla idempotenttir.

PATCH ise kısmi güncelleme içindir ve sonucu isteğin yazılış biçimine bağlıdır. "Adı Ayşe yap" biçimindeki bir PATCH fiilen idempotent çalışır. "Sayacı bir artır" biçimindeki PATCH ise her tekrarda farklı sonuç verir. Standart bu yüzden PATCH'i idempotent saymaz; tasarımcıya karar bırakır.

POST ise genellikle "yeni bir şey oluştur" ya da "bir işlem başlat" demektir. Bu nedenle tekrar, yeni bir kayıt doğurur. Ödeme, sipariş ve mesaj gönderme gibi akışların çoğu POST olduğu için idempotency anahtarı en çok burada gerekir.

Pratik bir kural olarak, mümkün olduğunda işlemi PUT benzeri "hedef durumu yaz" biçiminde tasarlayın. Bu mümkün değilse POST'a anahtar ekleyin.

Güvenli, idempotent ve atomik işlem arasındaki fark nedir?

Bu üç terim sık karıştırılır. Üçü de güvenilirlikle ilgilidir; ancak farklı soruları yanıtlar.

KavramSorduğu soruÖrnekDikkat
------------
Güvenli (safe)İstek sunucudaki durumu değiştiriyor mu?Ürün sayfasını okumakGüvenli her yöntem idempotenttir, tersi doğru değildir
IdempotentTekrar, sonucu değiştiriyor mu?Sipariş durumunu "onaylandı" yapmakDurum değişebilir, ama tekrar ek etki yaratmaz
Atomikİşlem ya tamamen olur ya hiç olmaz mı?Havale: bir hesaptan düşmek ve diğerine eklemekTekrarı engellemez, yarım kalmayı engeller
DeterministikAynı girdi aynı çıktıyı verir mi?Vergi hesaplama fonksiyonuYan etkileri hakkında bir şey söylemez

Özetle atomiklik "yarım kalma" riskini, idempotency ise "tekrar" riskini çözer. Güvenilir bir ödeme sistemi çoğu zaman ikisine de ihtiyaç duyar. Veritabanı katmanındaki işlem mantığını merak ediyorsanız back-end nedir yazımıza göz atabilirsiniz.

Idempotency anahtarı (idempotency key) nasıl çalışır?

Doğası gereği idempotent olmayan işlemler için çözüm, isteğe bir kimlik eklemektir. İstemci her mantıksal işlem için benzersiz bir anahtar üretir ve bunu istekle birlikte gönderir. Sunucu bu anahtarı ilk gördüğünde işlemi yapar ve sonucu anahtarla birlikte saklar. Aynı anahtar tekrar gelirse işlemi yeniden çalıştırmaz, saklanan sonucu aynen geri döndürür.

Stripe'ın resmi belgesi bu yaklaşımı iyi anlatır. Belgeye göre sağlayıcı, bir anahtarla yapılan ilk isteğin durum kodunu ve gövdesini saklar. Aynı anahtarla gelen tekrarlar kayıtlı yanıtı alır. Ayrıntıları Stripe idempotent istekler belgesinde görebilirsiniz.

Burada kritik nokta şudur: anahtar isteği değil, niyeti tanımlar. Müşteri bir kez "öde" demiştir. Bu niyetin kaç kez iletildiği önemli değildir; sonuç tek olmalıdır.

IETF'in HTTP API çalışma grubu, bu amaçla bir `Idempotency-Key` başlığını standartlaştırmaya çalışıyor. Bu çalışma henüz bir taslak olduğundan güncel durumunu IETF taslak sayfasından kontrol etmenizi öneririz.

Örnek senaryo ile açıklayalım. Bir müşteri sepetini onaylar ve uygulama "siparişi tamamla" isteğini bir anahtarla gönderir. Sunucu siparişi oluşturur, ama yanıt gecikir. Uygulama aynı anahtarla yeniden dener. Sunucu anahtarı tanır ve ikinci sipariş oluşturmak yerine ilk siparişin özetini döndürür. Müşteri tek sipariş görür; ekip tek fatura keser.

İstemci anahtarı nasıl üretmeli ve ne zaman yenilemeli?

Anahtarın kalitesi, mekanizmanın güvenilirliğini belirler. Üretim sırasında şu kurallara uyarsınız:

  • Anahtarı rastgele ve çakışma ihtimali çok düşük bir değerle üretin; genellikle UUID tercih edilir.
  • Anahtarı e-posta, telefon gibi kişisel verilerden türetmeyin.
  • Aynı mantıksal işlemin tüm tekrarlarında aynı anahtarı kullanın.
  • Kullanıcı yeni bir işlem başlattığında yeni anahtar üretin.
  • Anahtarı işlem başlamadan önce üretip saklayın; böylece uygulama çökse bile aynı anahtarla devam edebilirsiniz.

Son madde en sık atlananıdır. Anahtarı her yeniden denemede yeniden üretirseniz sunucu her isteği yeni sayar ve koruma tamamen işlevsiz kalır.

Ayrıca sağlayıcıların anahtar uzunluğu ve saklama süresi gibi sınırları vardır. Güncel değerleri kullandığınız sağlayıcının resmi belgesinden kontrol edin; biz burada rakam vermiyoruz.

Sunucu tarafında idempotency nasıl uygulanır?

Sunucu tarafında temel fikir basittir: işlemi yapmadan önce anahtarı kaydet, işlem bitince sonucu o kayda bağla. Uygulamada birkaç detay işi zorlaştırır.

İlk olarak anahtar kaydı ile iş mantığı aynı işlem sınırı içinde olmalıdır. Aksi halde ödeme alınır ama kayıt yazılamaz, ya da tersi olur. Veritabanındaki benzersizlik kısıtı burada işinize yarar, çünkü aynı anahtarı ikinci kez eklemeye çalışan istek reddedilir.

İkinci olarak eşzamanlı istekleri düşünmelisiniz. Aynı anahtarla iki istek aynı anda gelirse biri işlemeli, diğeri beklemeli ya da "işlem sürüyor" yanıtı almalıdır. Kilit mekanizması olmadan iki istek de "ilk" olduğunu sanabilir.

Üçüncü olarak sonucu yalnızca başarı durumunda değil, tutarlı hata durumlarında da saklamak gerekir. Doğrulama hatası gibi işlem hiç başlamadan biten istekleri ise saklamamak çoğu zaman daha doğrudur, çünkü kullanıcı düzeltip tekrar deneyebilmelidir.

Bir de anahtarın hangi kapsamda geçerli olduğu sorusu vardır. Anahtarı yalnızca kullanıcı bazında mı, yoksa uç nokta bazında mı değerlendireceksiniz? Genellikle kullanıcı ve işlem türü birlikte kapsam oluşturur. Böylece farklı kullanıcıların tesadüfen aynı anahtarı üretmesi birbirini etkilemez.

Aynı anahtar farklı içerikle gelirse ne olmalı?

Bu, tasarımın en çok gözden kaçan köşesidir. Müşteri aynı anahtarla ama farklı tutarla bir istek gönderirse ne yapmalısınız? İlk işlemin sonucunu döndürmek yanıltıcı olur; çünkü istemci ikinci tutarın işlendiğini sanabilir.

Sağlam sistemler, anahtarla birlikte isteğin içeriğinin özetini de saklar. Gelen istek, aynı anahtarın ilk isteğiyle uyuşmuyorsa sunucu açık bir hata döndürür. Stripe belgesi de bu yaklaşımı kullandığını, parametreler farklıysa hata verdiğini belirtir.

Bu davranış iki işe yarar. Birincisi, geliştiricinin yanlışlıkla anahtar kullandığı durumları erkenden yakalatır. İkincisi, kötü niyetli ya da hatalı bir istemcinin eski bir anahtarla yeni bir işlem yaptırmasını önler.

Tekrar eden isteğe sunucu hangi yanıtı vermelidir?

Sunucu, tanıdığı bir anahtarla ikinci kez karşılaştığında üç durumdan birindedir. Her birinde istemciye farklı bir mesaj vermek gerekir.

  • İlk istek tamamlanmışsa kayıtlı yanıtı aynen döndürün. İstemci için hiçbir şey değişmemiş gibi görünmelidir.
  • İlk istek hâlâ sürüyorsa "işlem devam ediyor" anlamına gelen bir yanıt verin; istemci kısa süre sonra yeniden sorabilir.
  • Anahtar aynı ama içerik farklıysa çakışmayı açıkça bildirin.

Burada önemli olan, istemcinin neyle karşılaştığını anlayabilmesidir. Sessizce yeni bir kayıt oluşturmak ya da belirsiz bir hata vermek, geliştiriciyi tahmin yürütmeye iter.

Yanıt gövdesine ayrıca bir not eklemek de işe yarar. Örneğin yanıtın kayıtlı sonuçtan geldiğini belirten bir başlık, destek ekibinin kayıtları okumasını kolaylaştırır. Hangi durum kodunu seçeceğiniz, kendi API sözleşmenize ve kullandığınız çerçeveye bağlıdır; HTTP durum kodlarının anlamı için RFC 9110'a başvurun.

Son olarak kayıtlı yanıtın ne kadar süre geçerli olduğunu istemciye açıklayın. Belgeleriniz bu süreyi ve davranışı net anlatırsa entegrasyon yapan ekipler tahmin yürütmek zorunda kalmaz. Açık bir belge, çoğu zaman en ucuz hata önleme yöntemidir.

Ağ zaman aşımı ve yeniden deneme (retry) idempotency ile nasıl birlikte çalışır?

Yeniden deneme (retry), başarısız görünen bir isteğin otomatik olarak tekrar gönderilmesidir. Tek başına tehlikelidir, çünkü ilk isteğin aslında başarılı olduğunu bilemezsiniz. Idempotency ise bu tehlikeyi ortadan kaldırır. İkisi birlikte "en az bir kez gönder, en fazla bir kez işle" davranışını sağlar.

İyi bir yeniden deneme stratejisi şu parçalardan oluşur:

  • Her denemede aynı idempotency anahtarını kullanmak.
  • Denemeler arasında giderek artan bekleme süresi (üstel geri çekilme) koymak.
  • Bekleme süresine rastgele küçük bir sapma (jitter) eklemek, böylece binlerce istemci aynı anda yüklenmez.
  • Deneme sayısına bir üst sınır koymak.
  • Yalnızca geçici hatalarda (zaman aşımı, bağlantı kopması, sunucu geçici olarak yanıt vermiyor) tekrar denemek.

Kalıcı hatalarda, örneğin yetki eksikliğinde, tekrar denemek yalnızca yükü artırır. Bu yüzden hata türünü ayırt etmek önemlidir.

Peki idempotency nedir sorusu burada neden yeniden gündeme gelir? Çünkü yeniden deneme mantığı, idempotency olmadan güvenle yazılamaz. Biri olmadan diğeri ya veri kaybına ya da çift işleme yol açar. Küçük bir ekip de olsanız bu ikiliyi birlikte tasarlamalısınız.

Arayüzde çift tıklamayı engellemek idempotency yerine geçer mi?

Hayır. Düğmeyi tıklandıktan sonra devre dışı bırakmak iyi bir alışkanlıktır; ancak yalnızca arayüzdeki tekrarı azaltır. Ağ katmanındaki yeniden denemeleri, mobil uygulamanın arka planda tekrar göndermesini ya da kullanıcının ikinci sekmeyi açmasını engellemez.

Bu yüzden iki katmanı birlikte düşünmelisiniz. Arayüz tarafında düğmeyi kilitleyin ve kullanıcıya "işleniyor" bilgisi gösterin. Sunucu tarafında ise gerçek korumayı idempotency ile sağlayın. Arayüz kullanıcı deneyimini iyileştirir, sunucu ise veriyi korur.

Ayrıca sayfa yenileme sorununu da unutmayın. Form gönderdikten sonra tarayıcıyı yenileyen kullanıcı aynı isteği yeniden gönderebilir. Başarılı işlemden sonra kullanıcıyı ayrı bir sonuç sayfasına yönlendirmek bu riski azaltır, ama yine de sunucu korumasının yerini almaz.

Mobil uygulamalarda durum daha da karışıktır. Kullanıcı uygulamayı arka plana atabilir, bağlantı değişebilir ve işletim sistemi isteği sonradan yeniden gönderebilir. Uygulamanız anahtarı yerel olarak saklarsa, yeniden açıldığında aynı işlemi aynı anahtarla sürdürebilir. Böylece kullanıcı aynı ödemeyi iki kez başlatmış olmaz.

Ödeme ve sipariş API'lerinde idempotency neden kritiktir?

Para hareketi, geri alınması en zor işlemdir. Bu nedenle ödeme sağlayıcıları idempotency anahtarını resmi belgelerinde öne çıkarır. Sipariş sistemlerinde de benzer risk vardır: çift sipariş, çift stok düşümü, çift fatura.

Örnek senaryo olarak küçük bir e-ticaret sitesini düşünün. Müşteri kartla ödeme yapar, 3D Secure doğrulaması biter, ancak mobil ağ koptuğu için sayfa yanıt alamaz. Müşteri tekrar dener. Idempotency yoksa iki tahsilat oluşur ve iade, destek yazışması, güven kaybı kaçınılmaz olur. Idempotency varsa ikinci istek kayıtlı sonucu alır ve müşteri tek ödeme görür.

Ödeme altyapısı seçerken sağlayıcının bu özelliği desteklediğine bakın. Konuyla ilgili sanal POS ve ödeme altyapısı seçimi yazımızda genel kriterleri bulabilirsiniz. Doğrulama adımındaki sorunlar için 3D Secure doğrulaması başarısız olduğunda neler yaptığımızı da anlattık.

Ekip içinde de ortak bir dil kurmak gerekir. Ürün sahibi için idempotency nedir sorusunun kısa cevabı şudur: müşterinin tek niyeti, tek sonuç üretir. Geliştirici bu cümleyi teknik gereksinime çevirir; test ekibi de onu kabul senaryosuna dönüştürür. Böylece konu yalnızca arka uç ekibinin işi olmaktan çıkar.

Olay işleme ve webhook'larda idempotency nedir?

Mesaj kuyrukları ve webhook'lar çoğunlukla "en az bir kez teslim" mantığıyla çalışır. Yani aynı olay size iki kez ulaşabilir. Bunu bir hata saymak yanlıştır; sistem bilerek tekrar gönderir, çünkü olayı kaybetmek tekrarlamaktan daha kötüdür.

Bu yüzden olayı alan tarafın idempotent olması gerekir. Buna idempotent tüketici (idempotent consumer) denir. Yaklaşım basittir: her olayın benzersiz bir kimliği vardır; tüketici işlediği kimlikleri kaydeder ve tanıdığı bir olayı ikinci kez işlemez.

Örneğin ödeme sağlayıcısı "ödeme tamamlandı" bildirimini iki kez gönderirse siparişi iki kez "kargoya hazırla" durumuna almamalısınız. Olay tabanlı sistemlerin ayrıntılarını event-driven mimari yazımızda anlattık; orada olay kimliği ve sıralama konularına da değiniyoruz.

Sıralama konusu da ayrı bir meseledir. Olaylar her zaman gönderildikleri sırayla gelmez. Dolayısıyla tüketici, eski bir olayın yeni bir durumu ezmesine izin vermemelidir. Olayın zaman damgasını ya da sürüm numarasını kontrol etmek bu riski azaltır. Bu kontrol de idempotency ile birlikte düşünülmesi gereken bir tamamlayıcıdır.

Doğal olarak idempotent tasarımlar nasıl kurulur?

Her zaman anahtar saklamanız gerekmez. Bazen işlemi baştan idempotent olacak şekilde tasarlayabilirsiniz. Anahtar fikri şudur: komutu "değişiklik" yerine "hedef durum" olarak ifade edin.

Tasarımİdempotent mi?Neden
---------
"Bakiyeyi 50 artır"HayırHer tekrar yeni bir artış ekler
"Bakiyeyi 150 yap"EvetTekrar aynı hedef değeri yazar
"Sepete bir ürün ekle"HayırHer tekrar adedi artırır
"Sepetteki ürün adedini 2 yap"EvetHedef adet sabittir
"Yeni kayıt oluştur"HayırHer tekrar yeni kimlik üretir
"Bu kimlikli kaydı oluştur veya güncelle"EvetKimlik sabit olduğu için tek kayıt kalır

Bu yaklaşım, istemcinin kimliği kendisinin üretmesini gerektirir. Sunucu kimlik üretiyorsa ilk istek ile tekrar istek farklı kimlik alır. Küçük bir tasarım tercihi, büyük bir güvenlik ağı sağlar.

Bu tasarım yaklaşımına bazen "hedef durum" modeli denir. Komut, ne yapılacağını değil, sonunda ne olması gerektiğini söyler. Böyle komutları tekrar etmek ek bir koruma gerektirmez. Elbette her iş bu biçime uymaz; bir hesaptan gerçekten para çekmek doğası gereği artımlıdır. O durumda anahtar yöntemine dönersiniz.

Mikroservislerde ve dağıtık işlemlerde idempotency nasıl yardımcı olur?

Birden çok servisin birlikte çalıştığı sistemlerde tek bir işlem zinciri halinde ilerleyen çağrılar vardır. Örneğin sipariş servisi stok servisini, stok servisi de kargo servisini çağırır. Zincirin ortasında bir servis zaman aşımına uğrarsa hangi adımların tamamlandığı belirsizleşir.

Bu belirsizlikte en güvenli yol, zincirdeki her adımı idempotent yapmaktır. Böylece koordinatör servis, emin olmadığı adımı yeniden gönderebilir. Adım zaten tamamlandıysa tekrar bir şey değiştirmez; tamamlanmadıysa şimdi tamamlanır.

Telafi işlemleri de aynı ilkeye uymalıdır. Bir ödemeyi iade eden adımı iki kez çalıştırmak, iki iade anlamına gelmemelidir. Bu nedenle iade istekleri de kendi anahtarlarını taşır.

Mikroservis kararlarının genel çerçevesi için Python ve Go arka uç karşılaştırmamıza bakabilirsiniz. Orada dil seçimini işlediğimiz için idempotency konusuna girmedik; bu yazı o boşluğu tamamlıyor.

Idempotency'nin sınırları ve riskleri nelerdir?

Idempotency her sorunu çözmez. Şu sınırları bilmelisiniz:

  • Yan etkiler: Anahtar, e-posta gönderimi veya bildirim gibi dış sistemlere ulaşan etkileri kendiliğinden korumaz. Bu etkiler de aynı anahtara bağlanmalıdır.
  • Saklama süresi: Anahtar kayıtları sonsuza kadar tutulmaz. Süre dolduktan sonra gelen tekrar yeni istek sayılabilir.
  • Depolama maliyeti: Her anahtar için yanıt saklamak ek alan ve bakım gerektirir.
  • Yanlış güven: Geliştirici idempotency var diye zaman aşımını ve hata yönetimini ihmal edebilir.
  • Anlamsal tuzak: PUT ile "hepsini değiştir" derseniz ve iki istemci aynı anda farklı değerler gönderirse, son yazan kazanır. Bu da idempotenttir ama istenmeyen bir sonuçtur.

Dolayısıyla idempotency bir güvenlik ağıdır; doğru iş mantığının yerine geçmez. Ayrıca kayıtlar kişisel veri içeriyorsa saklama süresi için hukuk ve KVKK gereklerini kendi uzmanınızla değerlendirin; bu yazı hukuki danışmanlık değildir.

Bu sınırları bilmek, beklentiyi doğru kurar. Idempotency nedir diye soran bir yönetici için en dürüst cevap şudur: ağın ve istemcilerin güvenilmez olduğu bir dünyada tekrarın zararını sınırlayan bir tasarım ilkesidir; hataları sihirli biçimde yok eden bir ürün değildir.

Idempotency uygularken en sık hangi hatalar yapılır?

Ekiplerde tekrar tekrar gördüğümüz hatalar genellikle küçük ayrıntılardan doğar. Şunlara dikkat edin:

  • Anahtarı her yeniden denemede yeniden üretmek.
  • Anahtar kaydını iş mantığından ayrı bir işlemde yazmak.
  • Yalnızca başarılı yanıtları saklayıp hataları hiç tutmamak.
  • İsteğin içeriğini anahtarla karşılaştırmamak.
  • Anahtarı herkesin tahmin edebileceği bir sayaçtan türetmek.
  • Webhook olaylarında benzersiz olay kimliğini kaydetmemek.
  • Dış sistemlere giden e-posta ve bildirimleri koruma dışında bırakmak.

Her madde tek başına küçük görünür. Ancak bir araya geldiklerinde çift tahsilat, çift fatura ya da yinelenen bildirim olarak ortaya çıkar. Bu yüzden kontrol listesini kod incelemesinin bir parçası yapmanızı öneririz.

Idempotent bir API'yi nasıl test edersiniz?

Test, mekanizmanın gerçekten çalıştığını gösterir. Aşağıdaki senaryoları sırayla deneyebilirsiniz:

  1. Aynı anahtarla aynı isteği iki kez gönderin ve ikinci yanıtın birincisiyle aynı olduğunu doğrulayın.
  2. Sonuç tablosunda yalnızca tek kayıt oluştuğunu kontrol edin.
  3. Aynı anahtarla farklı içerik göndererek sunucunun net bir hata verdiğini doğrulayın.
  4. Aynı anahtarla iki isteği aynı anda gönderin ve yalnızca birinin işlendiğini görün.
  5. İşlem ortasında bağlantıyı bilerek koparın, sonra aynı anahtarla tekrar deneyin.
  6. Saklama süresi dolduktan sonra davranışı gözlemleyin.

Sorun çıkarsa kayıtları incelemeniz gerekir. Hata ayıklama teknikleri yazımız bu aşamada işinize yarar. Sunucu erişim kayıtlarında tekrar eden istekleri görmek için log analizi aracımızı da deneyebilirsiniz.

Test ortamında gerçek para kullanmayın. Ödeme sağlayıcılarının sunduğu test modlarını tercih edin; böylece tekrar senaryolarını güvenle deneyebilirsiniz. Ayrıca bu testleri sürekli entegrasyon hattına eklerseniz, yeni bir değişiklik korumayı bozduğunda hemen fark edersiniz.

Serverless ve olay tabanlı sistemlerde idempotency nedir ve neden daha önemlidir?

Bulut fonksiyonları, platform tarafından otomatik yeniden denenebilir. Siz hiçbir şey yapmasanız bile bir fonksiyon aynı girdiyle iki kez çalışabilir. Bu nedenle sunucusuz (serverless) mimaride idempotent yazmak neredeyse zorunludur.

Serverless nedir yazımızda soğuk başlangıç ve maliyet konularını işledik. Burada yalnız şunu ekleyelim: fonksiyon zaman aşımına uğradığında platform işlemin bitip bitmediğini bilemez ve yeniden dener. Fonksiyonunuz bunu kaldırabilmelidir.

Benzer şekilde dönüşüm takibi gibi pazarlama entegrasyonlarında da tekrar eden olaylar çift sayıma yol açar. Meta Pixel ve Conversions API yinelenen etkinlik yazımızda aynı mantığın, olay kimliğiyle tekilleştirme biçiminde nasıl çalıştığını görebilirsiniz.

Geliştirici ve işletme için pratik kontrol listesi nedir?

Aşağıdaki liste hem teknik ekip hem de ürün sahibi için işe yarar:

  1. Para, stok veya kayıt oluşturan her POST akışını listeleyin.
  2. Her akış için idempotency anahtarı veya doğal idempotent tasarım seçin.
  3. İstemcide anahtarı işlem başlamadan üretin ve tüm denemelerde aynı tutun.
  4. Sunucuda anahtar kaydını iş mantığıyla aynı işlem sınırında yazın.
  5. Aynı anahtar farklı içerikle gelirse net bir hata döndürün.
  6. Eşzamanlı iki isteğe karşı kilit veya benzersizlik kısıtı koyun.
  7. Webhook ve kuyruk tüketicilerinde olay kimliğini kaydedin.
  8. Yeniden denemede üstel bekleme ve sınırlı deneme sayısı kullanın.
  9. Saklama süresini ve gizlilik gereklerini belgeleyin.
  10. Yukarıdaki test senaryolarını otomatik teste dönüştürün.

İşletme tarafında sağlayıcı seçerken belgelerinde idempotency desteğinin bulunup bulunmadığını sorun. Bu soru, sözleşme imzalamadan önce en değerli sorulardan biridir.

Bu listeyi bir kez doldurup bırakmayın. Yeni bir uç nokta eklendiğinde ya da sağlayıcı değiştiğinde yeniden gözden geçirin. İdempotency, bir kez kurulan bir özellikten çok, her değişiklikte korunması gereken bir alışkanlıktır.

Ne zaman uzman desteği almalısınız?

Küçük bir iç araçta bu önlemlerin hepsini kurmanız gerekmeyebilir. Ancak ödeme alıyorsanız, stok yönetiyorsanız ya da üçüncü taraf sistemlerle entegrasyon kuruyorsanız idempotency tasarımın başında düşünülmelidir. Sonradan eklemek, mevcut verilerdeki çiftleri temizlemekten çok daha pahalıdır.

Talha Aslan ve ekibi olarak entegrasyon ve API tasarımı konularında özel yazılım geliştirme hizmetimizle destek veriyoruz. Mevcut bir sistemin risk haritasını çıkarmak da bu işin bir parçasıdır.

Son olarak şunu hatırlayın: standartlar ve sağlayıcı belgeleri zamanla güncellenir. Burada anlatılan kavramlar kalıcıdır; ancak başlık adları, süre sınırları ve ayrıntılar için her zaman resmi belgeyi kontrol edin.

Karar verirken önce risk büyüklüğüne bakın. Hata yapıldığında müşteriden para almak, stok düşmek ya da hukuki bir yükümlülük doğmak gibi sonuçlar varsa korumayı baştan kurun. Sonuçlar küçük ve geri alınabilir ise daha hafif bir çözüm yeterli olabilir. Bu değerlendirmeyi yaparken idempotency nedir sorusunu kendi iş akışlarınıza uyarlayarak yanıtlamak en sağlıklı yoldur.

Sıkça Sorulan Sorular

Idempotency ile idempotent API aynı şey midir?
Idempotency bir özelliğin adıdır, idempotent API ise bu özelliği sağlayan arayüzdür. Yani idempotent bir API, aynı isteği birçok kez aldığında sonucu değiştirmez. Bunu ya yöntemin doğası gereği ya da idempotency anahtarı gibi bir mekanizmayla sağlar. Dolayısıyla biri kavramı, diğeri o kavramı uygulayan sistemi anlatır.
POST isteği idempotent olur mu?
Evet, olabilir; ancak varsayılan olarak değildir. RFC 9110 POST'u idempotent saymaz, çünkü her çağrı yeni bir kayıt oluşturabilir. Yine de istemci benzersiz bir idempotency anahtarı gönderir ve sunucu bunu saklarsa POST akışı pratikte idempotent davranır. Ödeme sağlayıcılarının çoğu bu yöntemi kendi belgelerinde açıkça önerir.
GET istekleri neden idempotent kabul edilir?
Çünkü GET yalnızca bilgi okumak için tasarlanmıştır ve sunucudaki durumu değiştirmemelidir. RFC 9110 GET'i güvenli yöntemler arasında sayar, güvenli her yöntem de idempotenttir. Ancak sizin API'niz GET isteğiyle kayıt silerse ya da sayaç artırırsa standardı çiğnemiş olursunuz ve önbellek gibi sistemler sorun çıkarır.
Idempotency anahtarını ne kadar süre saklamalıyım?
Süre, işleminizin tekrar gelme ihtimaline ve depolama kapasitenize bağlıdır. Anahtar, istemcinin makul bir şekilde yeniden deneyebileceği sürece kadar yaşamalıdır. Ödeme sağlayıcıları kendi saklama süresini belgelerinde yazar; güncel değeri resmi belgeden kontrol edin. Kişisel veri içeren yanıtlar için gizlilik gereklerini de hesaba katın.
Idempotency ile çift tahsilat tamamen önlenir mi?
Hayır, tek başına yeterli değildir ama en güçlü savunmalardan biridir. Anahtar yanlış üretilirse, her denemede değişirse ya da sunucu kaydı iş mantığından ayrı yazarsa çift işlem yine olabilir. Ayrıca müşteri iki ayrı sipariş verirse bu zaten iki ayrı niyettir. İzleme, mutabakat ve test de gerekir.
Idempotency yalnızca ödeme sistemleri için mi gereklidir?
Hayır. Sipariş, stok, e-posta gönderimi, webhook işleme, kuyruk tüketimi ve bulut fonksiyonları gibi tekrar riski taşıyan her yerde işe yarar. Para en görünür örnektir; ama tekrar eden bir bildirim ya da çift açılan bir destek kaydı da müşteri deneyimini bozar. Bu yüzden her entegrasyonda sorulacak bir sorudur.
  • idempotency
  • idempotent api
  • idempotency key
  • http yöntemleri
  • retry
  • çift tahsilat
  • api tasarımı
Paylaş:
Talha Aslan

Google Partner dijital pazarlama uzmanı. 2012’den beri SEO, Google Ads, web tasarım ve e-ticaret projelerinde sahada; bu blogda gördüğünüz her yazı o deneyimden çıkar.

Sıradaki proje

Projenizi konuşalım.

Talebiniz doğrudan Talha Aslan ve ekibine ulaşır: stratejiyi Talha kurar, uygulamayı deneyimli ekip yürütür. İlk istişare ücretsizdir; hedefinizi dinler, net bir yol haritasıyla döneriz.