Cron job, belirli bir zamanda ya da belirli aralıklarla kendiliğinden çalışan görevdir: her gece 02.00’de yedek almak, her sabah satış raporunu e-postayla göndermek, her saat başı kargo durumlarını güncellemek, ayın ilk günü abonelik faturalarını kesmek. Adını Unix’teki cron programından alır ve zamanı “dakika saat gün ay haftanın-günü” biçimindeki beş alanlı bir ifadeyle tanımlar. Görevi zamanlamak kolaydır; zor olan, görevin iki kez çalışmamasını, kaçırıldığında fark edilmesini ve sessizce bozulmamasını sağlamaktır. Bu yazıda cron ifadesini, zamanlanmış görevlerin en sık bozulma sebeplerini ve özel yazılım projelerimizde uyguladığımız güvenli kurulumu anlatıyoruz.
Cron ifadesi nasıl okunur?
Beş alan soldan sağa dakika (0-59), saat (0-23), ayın günü (1-31), ay (1-12) ve haftanın günüdür (0-6, pazar 0). Yıldız “her” anlamına gelir, virgül liste, tire aralık, eğik çizgi adım verir. Birkaç örnek:
- 0 2 * * *: her gün saat 02.00’de (gece yedeği, günlük rapor).
- */15 * * * *: her 15 dakikada bir (kargo veya ödeme durumu senkronizasyonu).
- 0 9 * * 1-5: hafta içi her gün 09.00’da (sabah özeti).
- 0 0 1 * *: her ayın ilk günü gece yarısı (aylık fatura, abonelik yenileme).
- 30 23 * * 0: her pazar 23.30’da (haftalık temizlik, eski kayıtların arşivlenmesi).
Cron ifadesi bir saat dilimine göre yorumlanır ve bu saat dilimi çoğu zaman sunucunun saatidir. Sunucu UTC’de çalışıyorsa “0 2 * * *” Türkiye saatiyle 05.00 demektir. Bu yüzden zamanlayıcının saat dilimi açıkça yazılır, varsayılana bırakılmaz; yaz saati uygulayan ülkelerde gece 02.00 ile 03.00 arasına kurulan görevler yılda bir gün hiç çalışmayabilir ya da iki kez çalışabilir.
Zamanlanmış görev nerede çalışır?
- Sunucu crontab’ı: tek sunuculu klasik kurulum. Basittir ama sunucu değişince görev unutulur ve kodla birlikte sürümlenmez.
- Uygulama içi zamanlayıcı: node-cron, Quartz, Hangfire gibi kütüphaneler. Kodla birlikte yaşar, ama uygulama birden fazla kopya çalışıyorsa görev her kopyada tetiklenir.
- Platform zamanlayıcısı: Kubernetes CronJob, bulut sağlayıcıların zamanlanmış tetikleyicileri, Vercel Cron. Tek tetikleme platform tarafından yapılır, iş kodunuzda kalır.
- İş kuyruğu ile tekrarlayan işler: BullMQ, Sidekiq gibi kuyruklar tekrarlı iş tanımını kendileri tutar, yeniden deneme ve geçmiş kaydını hazır verir.
En sık hata: görev iki kez çalışır
Uygulama ölçeklenip iki sunucuya çıktığında, içindeki zamanlayıcı da ikiye çıkar ve gece raporu iki kez gönderilir. Rapor için bu can sıkıcıdır; fatura kesimi ya da ödeme talimatı için ciddi bir hatadır. Görevin bir kez tetiklenmesi yetmez, işin kendisi de iki kez çalıştırıldığında aynı sonucu vermelidir. Bunu sağlamanın en sağlam yolu her çalıştırmaya bir dönem anahtarı vermektir: “aylık fatura, 2026-10” gibi. Görev başlarken bu anahtarla bir kayıt açmaya çalışır; kayıt zaten varsa başka bir kopya işi almıştır ve bu kopya çıkar. Aynı tablo, görevin ne zaman başladığını, ne zaman bittiğini ve hata verip vermediğini de tutar. Webhook alıcılarındaki olay kimliği yaklaşımıyla aynı fikirdir; webhook yazısında anlattık.
// Her ayın 1'i 03:00, Türkiye saati: '0 3 1 * *' (tz: Europe/Istanbul)
export async function monthlyInvoicesJob(now = new Date()) {
const period = formatInTimeZone(now, 'Europe/Istanbul', 'yyyy-MM');
const runKey = 'monthly-invoices:' + period;
// job_runs.run_key üzerinde tekil indeks: ikinci kopya buraya giremez.
const run = await db.jobRuns.insertIfAbsent({
runKey,
startedAt: new Date(),
status: 'running',
});
if (!run) return; // bu dönem zaten işlendi ya da işleniyor
try {
const subs = await db.subscriptions.dueForBilling(period);
for (const sub of subs) {
// Fatura da dönem + abonelik ile tekil: yarıda kalan iş güvenle yeniden başlar.
await billing.createInvoiceOnce(sub.id, period);
}
await db.jobRuns.finish(runKey, 'succeeded');
} catch (err) {
await db.jobRuns.finish(runKey, 'failed');
throw err; // hata izleme aracına gitsin
}
}Zamanlanmış görevin en tehlikeli hâli hata vermesi değil, hiç çalışmamasıdır: hata loglanır ve görülür, çalışmayan görev ise kimse fark edene kadar sessizdir. Her kritik görev “son başarılı çalışma ne zamandı” sorusuna cevap veren bir izleme ister.
Kaçırılan çalışma ve izleme
Sunucu tam görev saatinde yeniden başlatılırsa ya da yeni sürüm yayına alınırken zamanlayıcı kapalıysa o çalışma kaçırılır. Klasik cron kaçırılan çalışmayı telafi etmez. Bu yüzden kritik görevler iki biçimde korunur. Birincisi, görev yalnızca “şimdi”yi değil, işlenmemiş tüm dönemleri işler: aylık fatura görevi bu ayın değil, faturası kesilmemiş her dönemin işini yapar. İkincisi, dışarıdan izlenir: her başarılı çalışmada bir izleme adresine sinyal gönderilir, beklenen sürede sinyal gelmezse ekibe alarm düşer. Hata ve sinyal kayıtlarının nereye gideceğini hata izleme ve loglama yazısında anlattık; yedekleme görevleri için bu izleme zorunludur, ayrıntısı veri yedekleme yazısında.
Uzun süren görevler ve kuyruk
Cron bir tetikleyicidir, iş makinesi değildir. On bin aboneye fatura kesecek görevi tek döngüde yapmak, ortada bir hata çıktığında hangi faturanın kesildiğini belirsiz bırakır ve bir sonraki tetiklemeyle çakışabilir. Doğru kurgu, cron’un yalnızca işleri kuyruğa bırakması, kuyruk işçilerinin de her birini ayrı ayrı, yeniden denemeyle işlemesidir. Böylece bir abonede çıkan hata diğerlerini durdurmaz ve yük gün içine yayılır. Aynı kural e-fatura gibi dış servise bağlı görevlerde de geçerlidir: karşı servis yavaşladığında kuyruk bekler, görev zaman aşımına düşmez; bunu e-fatura entegrasyonu yazısında ele aldık. Görevlerin ayrı bir servise mi, aynı uygulamaya mı konacağı ise mimari bir karardır; mikroservis mi monolit mi yazısına bakabilirsiniz.
Kurulum öncesi kontrol listesi
- Saat dilimi açıkça yazıldı mı, yaz saati geçişine denk gelen saatler kullanılmadı mı?
- Uygulamanın birden fazla kopyası çalıştığında görev yine yalnızca bir kez tetikleniyor mu?
- İş iki kez çalışırsa aynı sonucu veriyor mu (dönem anahtarı, tekil indeks)?
- Kaçırılan dönem bir sonraki çalışmada telafi ediliyor mu?
- Son başarılı çalışma izleniyor ve süresi geçince alarm üretiyor mu?
- Görev tanımı kodla birlikte sürümleniyor ve CI/CD hattında test ediliyor mu?
Sonuç
Cron job, yazılımın “unutulmaması gereken” işlerini insan yerine yapan küçük bir parçadır; ama küçüklüğü onu kontrolsüz bırakmayı haklı çıkarmaz. Güvenli bir zamanlanmış görev açık saat dilimiyle tanımlanır, tek kopyada çalışır, iki kez çalıştığında zarar vermez, kaçırılan dönemi telafi eder ve çalışmadığında birilerine haber verir. Fatura, rapor, senkronizasyon ve yedekleme görevlerinizi bu ilkelerle kurmak istiyorsanız özel yazılım hizmetimize göz atın ya da doğrudan teklif alın.