n8n ile Hata Yönetimi ve Retry Mekanizması
Üretim ortamında bir iş akışı geceleri sessizce çöktüğünde ve sabah geldiğinde kimsenin haberdar olmadığını fark ettiğinizde, hata yönetiminin ne kadar kritik olduğunu anlıyorsunuz. n8n ile çalışırken bu durumu defalarca yaşadım. Görsel olarak her şey çok güzel görünüyor, workflow’lar akıyor, veriler işleniyor; ama bir API aşağı düştüğünde veya bir timeout oluştuğunda sistem sessizce ölüyor. Bu yazıda n8n’in hata yönetimi mekanizmalarını, retry stratejilerini ve gerçek üretim senaryolarında nasıl kullanmanız gerektiğini ele alacağım.
n8n’de Hata Yönetiminin Temelleri
n8n, node bazlı bir yapıya sahip olduğu için hatalar genellikle belirli bir node’da oluşur ve oradan sonraki node’lara yayılır. Varsayılan davranış şu şekilde çalışır: bir node hata verdiğinde execution durur ve tüm workflow başarısız olarak işaretlenir. Bu davranış küçük workflow’lar için kabul edilebilir, ama karmaşık iş akışlarında felakete davet çıkarmak gibidir.
n8n’de hata yönetiminin üç temel katmanı var:
- Node seviyesi hata yönetimi: Tek bir node’un hatalarını yakalamak
- Workflow seviyesi hata yönetimi: Tüm workflow’u saran genel hata işleme
- Error Workflow: Hata durumunda tetiklenen ayrı bir workflow
Bu üç katmanı doğru şekilde kullanmak, sağlam bir otomasyon altyapısı kurmanın anahtarı.
Try-Catch Mantığı: Error Output Kullanımı
n8n’deki her node’un bir “Error Output” özelliği var. Bu özelliği aktifleştirdiğinizde, node hata verdiğinde execution durmak yerine hata çıktısını özel bir bağlantı üzerinden ileriye taşırsınız. Bunu n8n arayüzünde node ayarlarından “Continue On Fail” seçeneğini açarak yapabilirsiniz.
Ama sadece “Continue On Fail” açmak yetmez. Hata bilgisini düzgün yakalamak ve sonraki adımlarda kullanmak için Expression kullanmanız gerekiyor. Hata mesajına şu şekilde ulaşırsınız:
# n8n Expression ile hata bilgisine erişim
{{ $node["HTTP Request"].error.message }}
{{ $node["HTTP Request"].error.description }}
{{ $node["HTTP Request"].error.httpCode }}
Bir HTTP isteği node’unda hata oluştuğunda bu bilgileri bir sonraki node’a taşıyıp loglayabilirsiniz. Örneğin bir Slack bildirim node’una şu mesajı gönderebilirsiniz:
# Hata bildirim mesajı için Expression
API Hatası: {{ $node["HTTP Request"].error.message }}
HTTP Kodu: {{ $node["HTTP Request"].error.httpCode }}
Zaman: {{ $now.format('yyyy-MM-dd HH:mm:ss') }}
Workflow: {{ $workflow.name }}
Retry Mekanizması: Teori ve Uygulama
Bir API’nin geçici olarak erişilemez olması, ağ kesintisi veya rate limiting gibi durumlarda hemen başarısız olmak yerine yeniden deneme yapmak çoğu zaman doğru çözümdür. n8n’de retry mekanizmasını iki farklı şekilde kurabilirsiniz.
Yerleşik Retry Seçeneği
n8n’in bazı node’larında (özellikle HTTP Request) doğrudan retry ayarı bulunur. Node ayarlarında “Retry on Fail” seçeneğini aktif ettiğinizde şu parametreleri yapılandırabilirsiniz:
- Max Tries: Kaç kez deneneceği (1-5 arası önerilir)
- Wait Between Tries: Denemeler arasındaki bekleme süresi (ms cinsinden)
Bu yerleşik seçenek basit senaryolar için yeterli, ama üretim ortamında genellikle daha sofistike bir yaklaşım gerekiyor.
Manuel Retry Loop Kurma
Üstel geri çekilme (exponential backoff) mantığıyla çalışan bir retry mekanizması kurmak için n8n’de şu yapıyı kullanabilirsiniz. Önce bir “Set” node’u ile retry sayacını başlatın:
# Set node'unda başlangıç değerleri
{
"retryCount": 0,
"maxRetries": 3,
"success": false,
"waitTime": 1000
}
Sonra bir “IF” node’u ile durumu kontrol edin:
# IF node'u için koşul Expression'ı
{{ $json.retryCount < $json.maxRetries && $json.success === false }}
Başarısız durumda tekrar denemeden önce bekleme süresi hesaplaması:
# Exponential backoff için bekleme süresi hesabı
# Her denemede süre iki katına çıkar: 1s, 2s, 4s, 8s...
{{ Math.pow(2, $json.retryCount) * 1000 }}
Bu yapıyı bir “Wait” node’u ile birleştirdiğinizde gerçek bir exponential backoff elde edersiniz. Retry sayacını artırmak için:
# Set node'unda retry sayacını artır
{
"retryCount": {{ $json.retryCount + 1 }},
"waitTime": {{ Math.pow(2, $json.retryCount + 1) * 1000 }}
}
Gerçek Dünya Senaryosu: E-Ticaret Sipariş Senkronizasyonu
Bir e-ticaret entegrasyonu üzerinde çalışırken yaşadığım gerçek bir problemi paylaşayım. WooCommerce’den siparişleri çekip bir ERP sistemine gönderen bir workflow kurmuştuk. ERP API’si bazen 503 dönüyordu, bazen de 30 saniye yanıt vermiyordu.
İlk kurduğumuz naive yaklaşım şuydu: Siparişleri çek, ERP’ye gönder, bitti. İlk hafta üç kez tüm workflow çöktü ve siparişler işlenemedi.
Düzeltilmiş versiyonda şu yapıyı kurduk. HTTP Request node’unda timeout ayarı:
# HTTP Request node timeout konfigürasyonu
{
"url": "https://erp.sirket.com/api/orders",
"method": "POST",
"timeout": 30000,
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 5000
}
Başarısız siparişleri bir ara tabloya kaydetmek için PostgreSQL node’u:
# Başarısız siparişleri kaydet
INSERT INTO failed_orders (
order_id,
error_message,
retry_count,
created_at,
next_retry_at
) VALUES (
'{{ $json.orderId }}',
'{{ $json.errorMessage }}',
0,
NOW(),
NOW() + INTERVAL '5 minutes'
);
Bu yaklaşımla başarısız siparişler kaybolmuyor, sistematik olarak yeniden deneniyor ve izlenebilir hale geliyor.
Error Workflow: Merkezi Hata Yönetimi
n8n’in en güçlü özelliklerinden biri Error Workflow konsepti. Bir workflow başarısız olduğunda otomatik olarak tetiklenen ayrı bir workflow tanımlayabilirsiniz. Bu, tüm workflow’larınız için merkezi bir hata yönetimi noktası oluşturmanızı sağlar.
Error Workflow içinde şu bilgilere erişebilirsiniz:
# Error Workflow'da kullanılabilir veriler
{{ $json.workflow.id }} # Hata veren workflow ID
{{ $json.workflow.name }} # Workflow adı
{{ $json.execution.id }} # Execution ID
{{ $json.execution.mode }} # Çalışma modu (manual/trigger vb.)
{{ $json.error.message }} # Hata mesajı
{{ $json.error.stack }} # Stack trace
{{ $json.error.node.name }} # Hata veren node adı
Merkezi hata yönetimi workflow’umu şu şekilde yapılandırıyorum:
- Hatayı bir veritabanına logla
- Kritiklik seviyesine göre bildirim gönder
- Belirli hata türleri için otomatik düzeltme dene
Hata seviyesini belirlemek için basit bir mantık:
# Hata kritiklik seviyesi belirleme
{{
$json.error.message.includes('timeout') ? 'WARNING' :
$json.error.message.includes('503') ? 'WARNING' :
$json.error.message.includes('401') ? 'CRITICAL' :
$json.error.message.includes('database') ? 'CRITICAL' :
'ERROR'
}}
Webhook’larda Hata Yönetimi
Webhook tabanlı workflow’larda hata yönetimi biraz farklı çalışır. Dışarıdan gelen bir istek işlenirken hata oluşursa, karşı tarafa anlamlı bir yanıt dönmeniz gerekir.
n8n’de webhook yanıtını kontrol etmek için “Respond to Webhook” node’unu kullanırsınız. Hata durumunda HTTP 500 yerine anlamlı bir yanıt döndürmek için:
# Başarılı yanıt yapısı
{
"status": "success",
"message": "İşlem başarıyla tamamlandı",
"processedAt": "{{ $now.toISO() }}",
"referenceId": "{{ $json.id }}"
}
# Hata yanıtı yapısı
{
"status": "error",
"message": "İşlem sırasında hata oluştu",
"errorCode": "{{ $json.errorCode || 'UNKNOWN_ERROR' }}",
"retryable": true,
"retryAfter": 60
}
Webhook workflow’larında önemli bir nokta: yanıt süresini kısa tutmak. Eğer işlem uzun sürüyorsa, webhook’u hemen kabul edip işlemi asenkron olarak yapın. Bunun için gelen veriyi bir kuyruğa (queue) ekleyip ayrı bir workflow ile işleyin.
Dead Letter Queue Implementasyonu
Birden fazla kez başarısız olan işlemleri izole etmek için “dead letter queue” mantığını n8n’de uygulamak mümkün. Maksimum retry sayısına ulaşmış işlemleri ayrı bir tabloya taşıyın:
# Maksimum retry'a ulaşmış kayıtları dead letter queue'ya taşı
INSERT INTO dead_letter_queue (
original_table,
original_id,
payload,
error_message,
failed_at,
retry_count
)
SELECT
'orders',
id,
payload,
last_error,
NOW(),
retry_count
FROM failed_orders
WHERE retry_count >= 3
AND next_retry_at < NOW();
DELETE FROM failed_orders
WHERE retry_count >= 3;
Bu kayıtlar otomatik sistem tarafından değil, manuel inceleme sonrası işleme alınır. Aylık periyodik olarak bu tabloyu inceleyip hata pattern’lerini analiz etmek, sisteminizdeki kronik sorunları tespit etmenizi sağlar.
n8n Function Node ile Özel Hata İşleme
Bazen yerleşik node’ların sağladığı hata yönetimi yeterli olmaz. Function node içinde JavaScript ile özel hata işleme mantığı yazabilirsiniz:
# Function node - Özel retry mantığı
const maxRetries = 3;
const baseDelay = 1000;
async function fetchWithRetry(url, options, attempt = 0) {
try {
const response = await $http.request({
url: url,
...options
});
return { success: true, data: response, attempts: attempt + 1 };
} catch (error) {
if (attempt < maxRetries - 1) {
const delay = baseDelay * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
return fetchWithRetry(url, options, attempt + 1);
}
return {
success: false,
error: error.message,
attempts: attempt + 1,
finalError: true
};
}
}
const result = await fetchWithRetry(
$input.first().json.apiUrl,
{ method: 'GET', headers: { 'Authorization': 'Bearer ' + $env.API_TOKEN } }
);
return [{ json: result }];
Bu yaklaşımla retry mantığını tamamen kontrol altına alıyorsunuz ve her deneme arasında ne olduğunu tam olarak görebiliyorsunuz.
Hata Bildirimlerini Akıllı Hale Getirmek
Üretimde karşılaştığım en büyük problemlerden biri “notification fatigue” yani bildirim yorgunluğu. Bir sistem sürekli hata veriyorsa ve her hata için Slack mesajı gönderiyorsa, ekip bu mesajları görmezden gelmeye başlıyor.
Bu sorunu çözmek için alert throttling uyguladım. Aynı türde hata belirli bir süre içinde birden fazla kez oluşursa sadece tek bildirim gönder:
# PostgreSQL'de alert throttle kontrolü
SELECT COUNT(*) as alert_count
FROM alert_log
WHERE workflow_id = '{{ $json.workflowId }}'
AND error_type = '{{ $json.errorType }}'
AND created_at > NOW() - INTERVAL '1 hour';
Eğer bu sorgu 0 dönerse bildirim gönder ve log’a ekle. 0’dan büyükse sessiz kal ama kayıt tut. Saatlik özet raporu ile tüm hataları toplu olarak raporla:
# Saatlik hata özeti sorgusu
SELECT
workflow_name,
error_type,
COUNT(*) as occurrence_count,
MIN(created_at) as first_occurrence,
MAX(created_at) as last_occurrence
FROM error_log
WHERE created_at > NOW() - INTERVAL '1 hour'
GROUP BY workflow_name, error_type
ORDER BY occurrence_count DESC;
İzleme ve Observability
Hata yönetimi sadece hataları yakalamaktan ibaret değil; aynı zamanda sisteminizin genel sağlığını izlemeniz gerekiyor. n8n execution’larını izlemek için şu metrikleri takip etmeyi öneririm:
- Başarı oranı: Son 24 saatte kaç execution başarılı, kaçı başarısız
- Ortalama execution süresi: Yavaşlayan workflow’ları erken tespit et
- Hata dağılımı: Hangi node’lar en çok hata veriyor
- Retry başarı oranı: Kaç retry başarıyla sonuçlandı
Bu metrikleri toplamak için her workflow sonunda basit bir log kaydı oluşturun:
# Her workflow sonunda execution metriği kaydet
INSERT INTO workflow_metrics (
workflow_id,
workflow_name,
execution_id,
status,
duration_ms,
items_processed,
error_count,
retry_count,
executed_at
) VALUES (
'{{ $workflow.id }}',
'{{ $workflow.name }}',
'{{ $execution.id }}',
'{{ $execution.status }}',
{{ Date.now() - $execution.startedAt }},
{{ $items().length }},
{{ $json.errorCount || 0 }},
{{ $json.retryCount || 0 }},
NOW()
);
Bu veriler zamanla sisteminizin güvenilirlik haritasını çıkarmanızı sağlar. Hangi entegrasyonların en sorunlu olduğunu, hangi saatlerde hataların arttığını ve hangi workflow’ların optimizasyona ihtiyaç duyduğunu net şekilde görürsünüz.
Sonuç
n8n güçlü bir otomasyon aracı, ama “çalışıyor” ile “sağlam çalışıyor” arasındaki fark tamamen hata yönetimine yapılan yatırımda yatıyor. Bir workflow’u görsel olarak birleştirmek kolay; onu gecenin üçünde kimse uyurken de güvenilir şekilde çalıştırmak bambaşka bir iş.
Burada anlattığım yaklaşımları sıfırdan uygulamak zorunda değilsiniz. Kendi sisteminizin gereksinimlerine göre seçin ve adapte edin. Küçük, kritik olmayan bir workflow için sadece “Continue on Fail” ve Slack bildirimi yeterli olabilir. Ama finansal veri işleyen veya müşteri siparişlerini yöneten bir workflow için dead letter queue, exponential backoff ve merkezi hata yönetimi zorunlu hale geliyor.
Pratikte şunu gördüm: İyi tasarlanmış hata yönetimi başlangıçta extra iş gibi görünüyor, ama ilk ciddi üretim olayından sonra o zamana değdiğini anlıyorsunuz. Workflow’larınız ne kadar güvenilir olursa, otomasyon ekibine olan güven o kadar artıyor ve daha fazla kritik süreci otomasyona taşıma fırsatı doğuyor. Bu da işin güzel yanı.
