---
title: "Dead-Letter Kuyruğunu Daha Kötü Yapmadan Replay Etmek"
description: "Naif replay kuyruğu yeniden zehirler ya da yan etkileri ikinci kez tetikler. Güvenli şekil: reset, dry-run, önce sandbox, select."
url: https://sade.dev/tr/notes/dead-letter-kuyrugunu-guvenle-replay-etmek/
lang: tr
author: "Muhammet Şafak"
published: 2026-06-19
updated: 2026-09-06
section: Note
tags: ["queue","dead-letter-queue","reliability","operations","architecture"]
summary: "Bir dead-letter kuyruğundan mesaj çıkarmak byte taşımak değil, canlı trafiği yeniden işlemektir. Naif bir replay, gerçek bir nedenle ölmüş mesajlarla kuyruğu yeniden zehirler ve zaten yarısı çalışmış yan etkileri ikinci kez tetikler. Güvenli şekil sıralıdır: envelope'u sıfırla ama mesaj id'sini ve trace id'yi koru, kesintinin imzasına göre seç, dry-run yap, sandbox'a yönlendir, production en sona kalsın."
---

# Dead-Letter Kuyruğunu Daha Kötü Yapmadan Replay Etmek

> Bir dead-letter kuyruğundan mesaj çıkarmak byte taşımak değil, canlı trafiği yeniden işlemektir. Naif bir replay, gerçek bir nedenle ölmüş mesajlarla kuyruğu yeniden zehirler ve zaten yarısı çalışmış yan etkileri ikinci kez tetikler. Güvenli şekil sıralıdır: envelope'u sıfırla ama mesaj id'sini ve trace id'yi koru, kesintinin imzasına göre seç, dry-run yap, sandbox'a yönlendir, production en sona kalsın.

Aşağı akıştaki bir API yirmi dakika düştü. Dört bin mesaj retry'larını tüketip dead-letter kuyruğuna düştü. API artık geri geldi, mesajlar hâlâ geçerli ve bariz hamle onları geldikleri yere geri koymak. Broker konsoluna uzanıp `orders.dlq`'dan `orders`'a mesaj taşımaya başlıyorsun.

Orada dur. Bir dead-letter kuyruğu bir bekleme alanıdır, mezarlık değil — ama mesajları oradan çıkarmak yüklü bir operasyondur ve "sadece geri taşı", atlatılmış bir kesintiyi ikinci bir olaya çevirmenin yoludur.

## Naif bir replay'in işi daha kötü yapmasının iki yolu

**Kuyruğu yeniden zehirler.** DLQ'n nadiren sadece kesintinin kurbanlarını tutar. Aralarına gerçek bir nedenle ölen mesajlar karışmıştır — bozuk bir payload, bir bug, yönlendirilemeyen bir URN — ve *onlar* replay ettiğin an yine başarısız olacak. Replay'in her şeyi körlemesine geri kürelerse, gerçekten bozuk mesajlar başarısız olur, tekrar DLQ'ya düşer, sen onları yine replay edersin. CPU yiyen, logları dolduran ve aslında başarılı olacak mesajları gömen bir döngü.

**Yan etkileri yeniden tetikler.** Üç denemeden sonra dead-letter'a düşen bir mesaj her seferinde *kısmen* çalışmış olabilir. Kart çekildi ama onay e-postası patladı; mesaj başarısız oldu, retry oldu, dead-letter'a düştü. Onu naifçe replay et, handler baştan sona yine çalışır — şimdi nihayet gönderdiği e-postanın üstüne ikinci bir tahsilat. Kuyruk bir mesaj taşıdı; müşterin iki kez faturalandı.

İki tuzak da replay'i "byte'ları geri taşı" sanmaktan gelir. Öyle değil. "**Bir mesajı sıfırla ve güvenle yeniden işle**" — ve bu kelimelerin her biri bir emniyet kilidi.

## Sıfırla, ama kimliği koru

Dead-letter'a düşmüş bir mesaj, nasıl öldüğünü anlatan ek bir blok taşır — neden, orijinal kuyruk, deneme sayısı. Onu replay etmek için **sıfırlaman** gerekir: o bloğu düşür ve deneme sayacını sıfıra geri al ki taze bir retry bütçesi alsın, anında yeniden tükenmesin.

Ama reset, *yeni* ile aynı şey değil. Mesajı tanımlayan her şeyi koru — id'sini, payload'ını ve hepsinden önemlisi korelasyon kimliğini (`trace_id`). İki nedenle:

- İzleyemediğin replay edilmiş bir mesaj operasyonel bir kör nokta. `trace_id`'yi koru, replay orijinal hatayla aynı trace'te görünsün.
- Korunan mesaj id'si, replay'i **retry'a güvenli** kılan şey. Tüketicilerin [idempotent](/tr/notes/idempotency-ayni-mesaj-iki-kez) ise — mesaj id'si üzerinden dedupe ediyorsa — zaten yarı başarılı olmuş bir mesajı replay etmek dedupe tarafından yakalanır, yeniden çalıştırılmaz. Idempotency ve replay ortaktır: idempotency, bir kuyruğu nefesini tutmadan replay etmeni sağlayan şeydir.

## Önce production'a doğrultma

Reset edilmiş ve idempotent olsa bile, bir replay canlı bir sisteme yazmadır. Güveni aşamalarla kazan:

- **Dry-run.** DLQ'yu oku ve neyin replay *edileceğini* raporla — sayılar, hedefler, nedenler — ve her mesajı dokunmadan geri koy. Tek el atmadan patlama yarıçapını öğrenirsin.
- **Sandbox.** Replay'i, tüketicilerinin dış yan etkileri stub'lanmış production dışı bir kuyruğa yönlendir. Mesajlar gerçek handler mantığından akar; kimse faturalandırılmaz. "İyi" mesajların gerçekten iyi olduğunu burada öğrenirsin.
- **Sonra production**, ilk ikisi sıkıcı hâle geldiğinde.

Sıra, herhangi bir tek adımdan daha önemli. Mesajlar "iyi görünüyor" diye doğrudan production'a replay etmek, ilk paragraftaki broker konsolunda onları taşıyan güvenin aynısıdır.

## Select et; saçma

Kesintinin kurbanları ortak bir imza taşır — bir zaman penceresi, bir hata `reason`'ı, bir URN. *O kümeyi* replay et, tüm kuyruğu değil. Reason'a göre seçmek, "timeout'tan ölen 4.000'i replay et" ile "4.000 timeout artı yine geri gelecek 30 gerçekten zehirli mesajı replay et" arasındaki farktır. Zehirli mesajlar replay etme sorunun değil; *düzeltme* sorunun ve onları görebildiğin DLQ'da kalmalılar.

## Resetleyemeyeceğin yan etki

İşte dürüst olmak gerekirse zor kısım. Reset envelope'u temizler; idempotency birebir replay'leri dedupe eder; sandbox sen test ederken production'ı korur. Ama production'a *kasıtlı* bir replay — gerçek olanı, aslında istediğin — handler'ı çalıştırır ve handler ne yapıyorsa onu yapar: tahsilat çeker, e-posta atar, üçüncü tarafı çağırır. Idempotency bir *kopyayı* durdurur; *amaçlanan* yeniden işlemenin yan etkileriyle birlikte işini yapmasını durdurmaz.

Temiz çözüm, bir handler'a replay çalıştırdığını bildirip zaten olmuş dış etkileri atlamasını sağlamak — veritabanı yazmasını yeniden yap, ama e-postayı yeniden gönderme. İş şu ki *o bayrağı nereye koyacaksın*: donmuş bir mesaj envelope'unda ekleyecek yer yok. Cevap, dağıtık izlemenin aynı kısıt için kullandığıyla aynı — onu **bant dışında** taşı, mesajın yanında giden ve runtime'ın handler'a sunduğu bir transport header olarak. Handler'ın kontrol edebileceği, yalnızca replay edilmiş mesajlarda set edilen, normal yolda hiçbir maliyeti olmayan bir `replay-bypass` işareti. En zahmetli parça ve en sona bırakılacak doğru parça — reset, dry-run, sandbox ve select replay'i rutin olacak kadar güvenli hâle getirdikten sonra.

Bir dead-letter kuyruğu, çeyreğin en kötü gününde sistemindeki en faydalı şeydir. Onu replay etmeyi olduğu şey gibi ele al — canlı trafiği yeniden işlemek — ve faydalı kalır. Byte taşımak gibi ele al ve DLQ'nun devam filmi gelir.

---

*İlgili:* [BabelQueue redrive-and-replay spec'i](https://babelqueue.com/docs/spec/1.x/redrive-and-replay) bu sıfırla-ve-yeniden-işle şeklini standartlaştırır; [`dlq-redrive` örneği](https://github.com/BabelQueue/babelqueue-examples/tree/main/dlq-redrive) ise onun çalıştırılabilir bir hâlidir.

## Sık sorulanlar

**DLQ mesajlarını doğrudan geri taşımak neden işi kötüleştirir?**

İki yolla. Kuyruk yeniden zehirlenir, çünkü DLQ gerçek bir nedenle ölmüş mesajları da tutar ve onlar replay ettiğiniz an yine başarısız olur. Yan etkiler de yeniden tetiklenir: üç denemeden sonra dead-letter'a düşen bir mesaj her seferinde kısmen çalışmış olabilir — kart çekilmiş, e-posta patlamıştır — ve naif bir replay handler'ı baştan sona yeniden çalıştırır.

**Idempotent bir tüketici replay için tek başına yeterli mi?**

Yeterli değil. Idempotency birebir tekrarı dedupe eder, ama production'a kasıtlı bir replay zaten çalışsın diye yapılır ve handler ne yapıyorsa onu yapar: tahsilat çeker, e-posta atar, üçüncü tarafı çağırır. Eksik parça, bant dışında bir transport header olarak taşınan replay işaretidir; handler onunla zaten olmuş dış etkileri atlayabilir.


## Kaynaklar

- [Using dead-letter queues in Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html) — AWS
- [Enterprise Integration Patterns: Dead Letter Channel](https://www.enterpriseintegrationpatterns.com/patterns/messaging/DeadLetterChannel.html) — Hohpe and Woolf
- [Consumer acknowledgements: redeliveries and idempotence](https://www.rabbitmq.com/docs/confirms) — RabbitMQ
