Mobil uygulama ile API arasında en pahalı hata türü, çift işlem. Kullanıcı ödeme butonuna basıyor, ağ kesiliyor, uygulama isteği tekrar gönderiyor ve iki sipariş oluşuyor. Bu bir hata değil, tasarım eksikliği: istek tekrarı mobil dünyada istisna değil, normal.
Sorunun kaynağı: cevabın kaybolması
Dikkat edilmesi gereken nokta, isteğin ulaşmaması değil. Çoğu zaman istek sunucuya ulaşıyor, işlem başarıyla tamamlanıyor, ama cevap istemciye dönerken kayboluyor. İstemci açısından sonuç belirsiz; tek makul davranışı tekrar denemek. Yani sorunu istemci tarafında "daha iyi hata yönetimiyle" çözemezsiniz. Sunucunun aynı işlemi iki kez yapmamayı garanti etmesi gerekiyor.
Idempotency anahtarı nasıl çalışır
Yaygın ve sağlam çözüm şu: istemci, işlemi başlatırken benzersiz bir anahtar üretir (UUID yeterli) ve bunu Idempotency-Key başlığında gönderir. Aynı işlemi tekrar denerken aynı anahtarı kullanır. Sunucu tarafında akış:
- Anahtar daha önce görülmediyse, işlemi yap ve anahtarı yanıtla birlikte kaydet.
- Anahtar daha önce görüldüyse ve işlem tamamlanmışsa, yeni işlem yapmadan kaydedilmiş yanıtı döndür.
- Anahtar görüldü ama işlem hâlâ sürüyorsa, 409 benzeri bir durumla "devam ediyor" bilgisini ver.
- Aynı anahtarla farklı bir istek gövdesi geldiyse hatayla reddet; bu bir istemci hatasıdır ve sessizce geçilmemeli.
Kritik ayrıntı: anahtar kaydı ile iş kaydı aynı veritabanı işlemi içinde yazılmalı. Ayrı yazılırsa, tam aradaki çökmede garantiyi kaybediyorsunuz ve çözmeye çalıştığınız sorunu daha nadir ama daha zor bulunur hale getiriyorsunuz.

Anahtarı üreten taraf önemli
Anahtar istemcide üretilmeli ve o işleme ait ekran açıldığında bir kez üretilip saklanmalı. Sık görülen hata, anahtarı her deneme öncesi yeniden üretmek; bu durumda mekanizma hiç çalışmıyor. Flutter tarafında pratik yaklaşım, anahtarı işlem durumunun (state) parçası yapmak — buton basımına bağlamamak.
Veritabanı seviyesinde ikinci hat
Uygulama katmanındaki kontrol yeterli görünse de, tek hat savunmaya güvenmiyoruz. Eşzamanlı iki isteğin ikisi de "anahtar yok" görüp devam edebiliyor. Bunun kesin çözümü veritabanı seviyesinde tekil (unique) kısıt: anahtar kolonuna tekil indeks koyup, ikinci yazmanın hata almasını sağlayın ve o hatayı "işlem zaten yapıldı" olarak yorumlayın. Kısıt ihlalini yakalamak, kilitlerle uğraşmaktan hem daha basit hem daha güvenilir.
Nerelerde uygulamalı
Her uca gerek yok. GET ve DELETE doğası gereği idempotent; asıl konu POST. Listemiz genelde şu: ödeme başlatma, sipariş oluşturma, para transferi, puan/bakiye hareketi, bildirim gönderimi ve dış servise yapılan masraflı çağrılar. Bir de saklama süresi belirleyin — 24 saat çoğu senaryo için makul; anahtar tablosunu sonsuza kadar büyütmenin faydası yok.
Dış servisle konuşurken zincir kırılıyor
Zor kısım, işlemin kendi veritabanınızda değil dışarıda gerçekleşmesi. Ödeme sağlayıcısına çağrı gönderdiniz, zaman aşımı aldınız; ödeme geçti mi geçmedi mi bilmiyorsunuz. Burada tek doğru davranış tahmin etmemek: işlemi "belirsiz" durumunda bırakıp, sağlayıcının sorgulama (query) ucundan durumu doğrulamak.
Bu yüzden ödeme akışlarında durum makinesini üç değerli değil dört değerli kuruyoruz: beklemede, belirsiz, başarılı, başarısız. "Belirsiz" durumunu atlamak, sahada gördüğümüz mutabakat sorunlarının en yaygın kaynağı. Ayrıca sağlayıcının kendi idempotency anahtarı desteği varsa, kendi anahtarınızla eşleştirip onu da gönderin; iki taraflı koruma, tek taraflıdan belirgin şekilde güvenli.
Mutabakat: son güvenlik ağı
Ne kadar iyi tasarlarsanız tasarlayın, uçlarda tutarsızlık oluşabiliyor. Bu yüzden ödeme veya bakiye barındıran her sistemde günlük bir mutabakat işi çalıştırıyoruz: kendi kayıtlarımızla sağlayıcının kayıtlarını karşılaştırıp farkları rapora düşen bir iş. Fark sayısı sıfırdan büyükse bir insan bakıyor. Bu iş, hiçbir zaman heyecan verici olmuyor ama bir kez bile fark yakaladığında kendini fazlasıyla amorti ediyor — çünkü aksi halde o farkı müşteri şikâyetiyle öğreniyorsunuz.

Ödeme, sipariş veya bakiye hareketi içeren bir API yönetiyorsanız ve mükerrer kayıt şikâyetleri geliyorsa, bu genellikle bir–iki günlük bir müdahaleyle kapanan bir konu. İletişim sayfamızdan bize yazın; mevcut uçlarınıza bakıp hangilerinin korumaya ihtiyacı olduğunu birlikte çıkaralım.