İçeriklere dön
    Backend ve VeritabanıGeliştiriciKarar rehberi

    Serverless Her Proje İçin Doğru mu? Queue ve Worker Ne Zaman Gerekir?

    Serverless function ne zaman yeterli, queue ve worker ne zaman gerekir? Timeout, retry, idempotency, DLQ ve background job mimarisini öğrenin.

    Yayın: 23 Ağustos 2026Güncelleme: 23 Ağustos 2026InoviqLab
    Kullanıcı request’inin serverless API’den queue’ya ve worker’a ayrılarak işlendiğini gösteren asynchronous backend mimarisi.
    Hedef kitle
    Geliştirici
    İçerik türü
    Karar rehberi
    Evergreen rehber. Yayın ve güncelleme tarihi makale metadatasında tutulur.
    ServerlessQueueWorkerBackground JobsAWS LambdaSQSVercelCloudflare QueuesIdempotencyDLQ

    Kısa özet Serverless fonksiyonlar API endpoint’leri, kısa süreli database işlemleri, webhook’lar ve I/O ağırlıklı işlerde son derece kullanışlıdır. Ancak bir işlemin uzun sürmesi, kullanıcı response’unu gereksiz yere bekletmesi, yeniden denenmesi gerekmesi, ani trafik artışlarını tamponlaması veya ayrı concurrency kontrolü gerektirmesi durumunda işi HTTP request’in içinde tutmak yerine queue + worker mimarisi daha sağlıklı olabilir. Buradaki kritik ayrım süre değildir. Vercel, Fluid Compute kullanan Pro ve Enterprise Node.js/Python Functions için 2026’da 30 dakikaya kadar execution süresini beta olarak desteklemeye başladı; AWS Lambda ise 15 dakikaya kadar çalışabiliyor. Buna rağmen bir fonksiyonun 10 veya 20 dakika çalışabilmesi, o işi mutlaka request içerisinde çalıştırmanız gerektiği anlamına gelmez. (Vercel)

    Asıl soru şudur:

    Kullanıcı bu işlemin bitmesini gerçekten HTTP response gelmeden önce beklemek zorunda mı?

    Cevap hayırsa, queue + worker değerlendirilmelidir.

    Kısa doğrudan cevap

    Serverless çoğu modern web uygulaması için güçlü bir varsayılandır ancak her iş yükünün tek çözümü değildir. Şu tip işlemler request içinde kalabilir: Login CRUD Kısa database işlemleri Küçük webhook doğrulaması Kullanıcıya hemen gerekli hesaplamalar Şu tip işler queue + worker için daha güçlü adaydır: PDF/rapor oluşturma Büyük dosya işleme Video veya medya dönüşümü Toplu e-posta Uzun AI işlemleri Web scraping Binlerce kaydı senkronize etme Büyük import/export Tekrar denenmesi gereken üçüncü taraf API işleri Kullanıcının beklemesinin gerekmediği operasyonlar Temel mimari: User Request ↓ API ↓ Job oluştur ↓ Queue ↓ Worker ↓ İşle ↓ Sonucu kaydet ↓ Kullanıcıya durum göster olabilir.

    Önce kavramları ayıralım: serverless, queue ve worker nedir?

    Serverless function

    Bir HTTP request, event veya başka trigger geldiğinde çalışan yönetilen compute birimidir. Örneğin: POST /api/reservation ↓ Vercel Function ↓ Database ↓ Response Vercel Functions sunucu yönetmeden backend kodu çalıştırmayı ve talebe göre ölçeklenmeyi sağlıyor. Platform özellikle API/database bağlantıları ve I/O ağırlıklı AI işlerini Functions için uygun kullanım alanları arasında gösteriyor. (Vercel) Queue Queue, yapılacak işleri geçici olarak saklayan mesaj kuyruğudur. Producer ↓ Queue ↓ Consumer AWS SQS queue’ların distributed application bileşenlerini birbirinden ayırmak ve bağımsız ölçeklemek için kullanılabileceğini belirtiyor. Cloudflare Queues da queue’yu request’ten işi ayırmak, downstream API çağrılarını tamponlamak ve batch işlemek için konumlandırıyor. (AWS Dokümantasyonu) Worker Worker queue içinden işi alıp gerçekleştiren consumer’dır. Örneğin: Queue: generate-pdf

    Worker:

    1. Job'u al

    2. Veriyi çek

    3. PDF oluştur

    4. Storage'a yükle

    5. Job'u completed yap

    Worker:

    • ayrı container,
    • uzun yaşayan Node.js process,
    • serverless consumer,
    • Cloudflare Worker,

    Lambda consumer olabilir. Yani: Queue + worker kullanmak serverless’tan tamamen çıkmak anlamına gelmez. Worker’ın kendisi de serverless olabilir.

    Serverless neden bu kadar güçlü?

    Çünkü birçok uygulama request/response ağırlıklıdır. Örneğin: User ↓ GET /dashboard ↓ Database query ↓ JSON veya: POST /customer ↓ Validation ↓ Database insert ↓ Response Bu tip işlemlerde:

    • altyapı yönetimi azdır,
    • trafikle otomatik ölçeklenebilir,
    • ayrı server process yönetmeniz gerekmez,

    düşük trafik döneminde sürekli çalışan compute taşımayabilirsiniz. Bu nedenle: “Worker kullanabiliyoruz, o halde bütün backend’i worker yapalım.” da doğru değildir.

    Ne zaman problem başlıyor?

    Bir endpoint şu hale geldiğinde:

    POST /create-report

    1. Database'ten 20.000 kayıt çek

    1. 10 API çağrısı yap

    3. AI summary oluştur

    4. PDF üret

    5. PDF'i S3'e yükle

    6. E-mail gönder

    7. Database status güncelle

    8. Response döndür

    kullanıcı bütün zinciri beklemeye başlar. İşlem: 500 ms değil: 40 saniye 3 dakika 10 dakika sürebilir. Burada artık asıl soru function timeout değildir. Asıl sorunlar: Kullanıcının beklemesi Request’in açık tutulması Retry Partial failure İşin yeniden başlatılması Third-party API limitleri Traffic burst Concurrency haline gelir.

    “Function süresini artırırım” neden her zaman çözüm değil?

    Platformlar bugün geçmişe göre çok daha uzun serverless invocation’lara izin veriyor. Örneğin AWS Lambda: Maximum timeout: 900 saniye / 15 dakika destekliyor. (AWS Dokümantasyonu) Vercel ise Haziran 2026’da Fluid Compute kullanan Pro/Enterprise Node.js ve Python Functions için:

    maxDuration = 1800

    yani 30 dakikaya kadar çalışma süresini beta olarak duyurdu. (Vercel) Bu önemli bir gelişmedir. Ama: Function 30 dk çalışabiliyor ile: İş request içinde 30 dk çalışmalı aynı karar değildir. Süreden daha önemli 7 soru Bir işi queue’ya taşımadan önce şu sorulara bakın.

    1. Kullanıcı sonucu hemen bekliyor mu?

    Örneğin: Login için evet. Ama: 500 sayfalık PDF export için kullanıcı: Rapor hazırlanıyor durumunu görebilir.

    2. İş başarısız olursa yeniden denenmeli mi?

    Örneğin: e-mail provider timeout oldu.

    Kullanıcının tekrar form göndermesi mi gerekecek?

    Yoksa sistem otomatik retry mı yapacak?

    Retry gerekiyorsa queue önemli avantaj sağlar.

    3. İş aynı anda çok fazla tetiklenebilir mi?

    Örneğin: 10 kullanıcı yerine: 10.000 webhook aynı anda gelebilir. Queue burada buffer olur: 10.000 message ↓ Queue ↓

    50 concurrent worker

    4. Downstream sistemin rate limit’i var mı?

    Örneğin harici API:

    100 request/minute izin veriyor. Web uygulamanız bir anda: 5.000 request üretebilir. Queue tüketim hızını sınırlandırabilir.

    5. İş kısmen başarılı olabilir mi?

    Örneğin: PDF oluşturuldu ✅ Upload edildi ✅ Email gönderimi ❌ Request içinde bütün işlemi tekrar çalıştırırsanız: PDF tekrar üretilebilir. Queue/job state ise hangi aşamanın başarısız olduğunu takip etmeyi kolaylaştırabilir.

    6. İş tekrar çalıştırıldığında zarar verir mi?

    Örneğin: chargeCustomer iki kere çalışırsa: müşteri iki kez ücretlenebilir. Bu durumda idempotency kritik hale gelir.

    7. İşin concurrency’sini web trafiğinden ayrı yönetmek istiyor musunuz?

    Web API:

    1.000 concurrent request karşılayabilir. Ama image processing sistemi: maksimum 10 paralel job çalıştırmak isteyebilir. Queue bu iki ölçekleme profilini birbirinden ayırır. Karar tablosu İş Request içinde after Queue + Worker Login ✅ ❌ ❌ CRUD ✅ ❌ Genelde ❌ Analytics log ❌ ✅ Bazen Basit audit log ❌ ✅ Bazen E-mail gönderme Bazen Bazen ✅ yüksek hacimde PDF oluşturma Küçükse ❌ ✅ CSV export Küçükse ❌ ✅ büyükse Video processing ❌ ❌ ✅ AI document analysis Bazen Bazen ✅ uzun/çok adımlıysa Bulk import ❌ ❌ ✅ Web scraping ❌ ❌ ✅ 10.000 kaydı sync ❌ ❌

    Next.js after queue yerine kullanılabilir mi?

    Bazı durumlarda. Next.js after: response tamamlandıktan sonra iş çalıştırmaya izin verir. Örneğin:

    import { after } from 'next/server'
    export async function POST {
    await saveOrder

    after(async => {

    await logAnalytics

    })

    return Response.json({ success: true })

    } Next.js özellikle: logging analytics response’u bloklamaması gereken side effect’ler için after kullanımını örnek gösteriyor. (Next.js) Ama after durable queue değildir En önemli fark budur. after hâlâ bulunduğu function invocation’ın maximum duration sınırına bağlıdır. Vercel’in waitUntil dokümantasyonu da promise’lerin function timeout’u ile aynı yaşam süresine sahip olduğunu ve function timeout olursa bu arka plan işlerinin iptal edileceğini açıkça belirtiyor. (Vercel) Dolayısıyla: after ≠ durable queue after için iyi işler Örneğin: Analytics Logging Cache update Kısa notification Queue için daha iyi işler Rapor üret 500 MB dosya işle 1000 müşteri senkronize et Third-party API retry AI batch process Video encode Bulk email Çünkü queue mesajı request lifecycle’dan bağımsız yaşayabilir. En tehlikeli pattern: gerçek “fire-and-forget” Örneğin:

    export async function POST {

    sendEmail

    return Response.json({
    • ok: true,

    }) } Burada sendEmail await edilmedi. Developer: “Background’da çalışır.” diye düşünebilir. Serverless ortamda invocation response sonrası durdurulabilir. Vercel de yönetilmeyen fire-and-forget işlemler yerine waitUntil veya Next.js after kullanılmasını öneriyor. (Vercel) Daha kritik işlerde ise queue tercih edilmelidir.

    Queue hangi problemi çözüyor?

    Queue’nun önemli görevi:

    İş üretimi ile iş tüketimini birbirinden ayırmak. Örneğin: User ↓ POST /export ↓ Job oluştur ↓ Queue'ya yaz ↓ 202 Accepted Kullanıcı response’u: {

    • "jobId": "job_123",
    "status": "queued"

    } olarak hemen alabilir. Arka planda: Worker ↓ job_123 ↓ Export oluştur ↓ Storage ↓

    status=completed

    çalışır. HTTP 202 Accepted modeli Asenkron işler için yaygın yaklaşım: POST /reports cevabı: {

    • "id": "report_123",
    "status": "processing"

    } olabilir. Sonra client: GET /reports/report_123 ile durum sorgular. Alternatif: WebSocket Server-Sent Events Push notification Email ile tamamlanma bildirilebilir. Queue'nun en büyük faydalarından biri buffering Örneğin SaaS sisteminize aynı anda: 50.000 webhook geldi. Request sırasında doğrudan downstream API’ye gönderirseniz: Input hızınız > processing kapasiteniz olabilir. Queue araya girer: 50.000 incoming events ↓ Queue ↓ Consumer kapasitesi kadar işlem Cloudflare Queues dokümantasyonu da queue’ların downstream servis çağrılarını buffer/batch etmek ve bileşenleri birbirinden ayırmak için kullanılabileceğini belirtiyor. (Cloudflare Docs) Queue aynı zamanda backpressure sağlar Sisteminiz saniyede: 100 job üretebiliyor. Worker: 40 job/s işleyebiliyor. Queue backlog: 60 job/s büyür. Bu görünür hale geldiğinde:

    • worker artırabilirsiniz,
    • producer hızını azaltabilirsiniz,

    alert oluşturabilirsiniz. Queue olmadan bu yük downstream service’i doğrudan ezebilir.

    Worker concurrency neden önemlidir?

    Örneğin database aynı anda:

    1000 ağır report query kaldıramayabilir. Worker concurrency:

    max = 10

    yapılabilir. Cloudflare Queues consumer concurrency’sini backlog, failure oranı ve max_concurrency değerine göre ölçekleyebiliyor; max_concurrency ile üst sınır konulabiliyor. (Cloudflare Docs) Benzer concurrency kontrolü farklı queue/worker altyapılarında da kurulabilir. Queue kullanmaya başladığınızda yeni problem: duplicate delivery Queue sistemlerinin önemli bir özelliği: Bir mesaj bazı durumlarda birden fazla kez teslim edilebilir. AWS SQS standard queue’lar at-least-once delivery kullanır ve AWS consumer uygulamaların aynı mesajı birden fazla kez işlediğinde zarar görmeyecek şekilde idempotent tasarlanmasını önerir. (AWS Dokümantasyonu) Cloudflare Queues da varsayılan olarak at-least-once delivery sağlar ve nadir durumlarda mesajın birden fazla kez teslim edilebileceğini belirtir. (Cloudflare Docs) Bu nedenle: Queue ekledim, güvenilir oldu. demek yetmez. Idempotency gerekir.

    Idempotency nedir?

    Aynı işlemin iki kez yapılmasının sonucu bir kez yapılmasıyla aynı olmalıdır. Örneğin: Job: send-welcome-email iki kez işlenirse: 2 e-mail gitmesini istemeyebilirsiniz. İş için unique key: welcome-email:user_123 tutabilirsiniz. İş ikinci kez gelirse: already_processed denir. Payment örneği Riskli: async function processPayment(job) {

    await paymentProvider.charge({
    • amount: job.amount,

    }) } Aynı job yeniden teslim edilirse: 2 charge oluşabilir. Daha iyi:

    await paymentProvider.charge({
    • amount: job.amount,
    • idempotencyKey: job.id,

    }) ve uygulama tarafında da işlenmiş job kaydı tutulabilir. Cloudflare da at-least-once işlerde message için unique ID oluşturup bunu database primary key veya upstream API idempotency key olarak kullanmayı öneriyor. (Cloudflare Docs)

    Retry nasıl tasarlanmalı?

    Her hata retry edilmemelidir. Örneğin: Retry edilebilir Timeout 429 Rate Limit 503 Service Unavailable Temporary network error Genellikle retry edilmemeli Invalid email Validation error 403 Permission denied Malformed payload Retry stratejisi: Attempt 1 ↓ 5 sn ↓ Attempt 2 ↓ 30 sn ↓ Attempt 3 ↓ 5 dk gibi exponential backoff kullanabilir.

    Sonsuz retry neden kötü?

    İş hiçbir zaman başarılı olmayacaksa:

    Job ↓ Retry ↓ Retry ↓ Retry ↓ Retry... şunlara yol açabilir: Queue maliyeti Downstream API yükü Log gürültüsü Backlog büyümesi Bu nedenle retry limitinden sonra: Dead Letter Queue kullanılabilir.

    Dead Letter Queue nedir?

    DLQ:

    Belirli sayıda denemeye rağmen işlenemeyen mesajların taşındığı ayrı kuyruktur. AWS SQS DLQ’ları işlenemeyen mesajları izole edip neden başarısız olduklarını incelemek için kullanıyor; mesajlar daha sonra tekrar source queue’ya redrive edilebiliyor. (AWS Dokümantasyonu) Cloudflare Queues da max_retries sonrasında mesajı configured DLQ’ya gönderebiliyor. (Cloudflare Docs) DLQ “çöp kutusu” olmamalı Şu model yanlış: Failed ↓ DLQ ↓ Bir daha kimse bakmıyor DLQ için alert gerekir. Örneğin: DLQ message count > 0 ↓ Alert

    ve ardından:

    • Neden başarısız?

    Bug mı?

    Data problemi mi?

    Provider outage mı?

    incelenmelidir. Retry + idempotency birlikte düşünülmeli Retry açtıysanız duplicate ihtimalini kabul etmiş olursunuz. Dolayısıyla: Retry ile: Idempotency aynı tasarımın iki parçasıdır. Özellikle: payment email booking inventory invoice webhook processing işlerinde önemlidir.

    Queue mesajına ne koymalısınız?

    Riskli:

    {

    "fullCustomer": {
    "...": "çok büyük veri"

    } } Daha sağlıklı: {

    • "jobId": "job_123",
    • "customerId": "customer_55",
    "type": "generate_report"

    } Worker güncel veriyi database’ten çekebilir. Avantaj: Queue payload küçülür Hassas veri daha az kopyalanır Büyük message sorunları azalır Ancak job sırasında verinin değişmesi kritikse gerekli snapshot bilgisi ayrıca saklanabilir. Queue bir database değildir Queue: iş bekleme alanı olarak düşünülmelidir. Job state için ayrıca database tutulabilir: jobs id

    type

    status progress attempts createdAt startedAt completedAt error resultUrl Böylece kullanıcıya: Queued Processing Completed Failed gösterilebilir. Worker yalnızca işlem yapmalı, kullanıcı session'ına bağımlı olmamalı Request sırasında: cookie session request headers vardır. Worker saatler sonra çalışabilir. Dolayısıyla: Request session üzerine güvenmemelidir. Job’a güvenli identity/context aktarılmalıdır. Örneğin: {

    • "jobId": "123",
    • "tenantId": "company_a",
    "requestedBy": "user_1"

    } Worker authorization sınırlarını yeniden uygulamalıdır. Multi-tenant queue sisteminde tenant sınırına dikkat Bir worker: Tenant A job çalıştırırken yanlışlıkla: Tenant B data işlememelidir. Tenant ID:

    • job metadata,
    • server-side doğrulanmış context,

    database authorization üzerinden uygulanmalıdır. Agent veya worker’a gelen payload’a körü körüne güvenilmemelidir.

    Ne zaman ayrı queue'lar oluşturmalısınız?

    Her iş için tek queue başlangıçta yeterli olabilir. Ama zamanla: email report image AI billing aynı queue’da olursa problem oluşabilir. Örneğin 2.000 ağır AI job: password reset e-mail işlerini geciktirebilir. Bu nedenle farklı SLA/risk/compute profilleri için ayrı queue düşünülebilir: email-queue report-queue ai-queue billing-queue Cloudflare da farklı use case ve processing gereksinimlerini ayırmak için birden fazla queue oluşturulabileceğini belirtiyor. (Cloudflare Docs)

    Öncelikli işler nasıl ayrılabilir?

    Örneğin: high-priority normal bulk queue’ları. High Password reset Critical notification Normal Report Bulk 100.000 kayıt import Böylece büyük batch işlemi kullanıcıya kritik işi bloklamaz.

    CPU-heavy işler serverless için uygun mu?

    “Serverless CPU işi yapamaz” demek doğru değildir. Ancak:

    • CPU süresi,
    • memory,
    • execution limit,
    • maliyet,

    parallelism kontrol edilmelidir. Örneğin Vercel Fluid Compute CPU kullanımını active CPU time ve provisioned memory üzerinden ölçüyor; I/O bekleme sürelerinde active CPU billing durabiliyor. (Vercel) Ama sürekli: 30 dakika tam CPU kullanan binlerce media-processing job için:

    • container worker,
    • batch compute,

    specialized service daha uygun olabilir.

    AI işlemlerinde serverless mı queue mu?

    İkisi de kullanılabilir. Kullanıcı sohbeti User ↓ AI streaming ↓ Response serverless function için uygun olabilir. Vercel uzun LLM reasoning ve tool-call işlemlerini 30 dakikaya kadar uzatılmış Functions kullanım alanları arasında sayıyor. (Vercel) 100 belge analiz edilecek Upload ↓ 100 documents ↓ AI extract ↓ Database queue daha mantıklı olabilir. Çünkü:

    • progress gerekiyor,
    • retry gerekiyor,
    • provider rate limit var,

    işlem kullanıcı request’inden bağımsız.

    Bir iş 5 saniye sürüyor diye queue gereksiz mi?

    Hayır. Süre tek kriter değildir. Örneğin: Send webhook yalnızca 300 ms sürebilir. Ama hedef servis: bazen offline ise retry gerekir. Dolayısıyla 300 ms’lik işlem bile queue için uygun olabilir.

    Bir iş 5 dakika sürüyor diye queue zorunlu mu?

    Yine hayır. Örneğin kullanıcı: AI research response bekliyor ve streaming ile sonuç alıyorsa uzun function mantıklı olabilir. Bu nedenle: Duration tek başına mimari karar değildir. Queue eklemenin maliyeti var Queue + worker mimarisi ücretsiz karmaşıklık değildir. Yeni bileşenler: Queue Worker Job schema Retry DLQ Monitoring Idempotency Job state eklenir. Küçük uygulamada: sendEmail için ayrı distributed job platformu kurmak gereksiz olabilir. Queue kullanmayın diyebileceğimiz durumlar Örneğin: İş çok kısa Kullanıcı sonucu hemen bekliyor Retry ihtiyacı yok Hacim düşük Partial failure riski düşük Operasyon basit ise request içinde kalabilir. Basit async side effect için queue fazla olabilir Örneğin: User profile updated ↓ analytics event Burada Next.js: after( => { sendAnalytics }) yeterli olabilir. after response’u bloklamadan çalışabiliyor ancak function’ın configured lifetime sınırında kalıyor. (Next.js) Bu işlem kritik business event ise durable queue daha güçlü olabilir. Kritik ayrım: Best-effort vs Durable Best-effort olabilir Analytics Non-critical log Cache warm İş kaybolursa ciddi business problemi olmayabilir. Durable olması gereken Payment event Invoice creation Order fulfillment Reservation confirmation İşin kaybolması kabul edilemez. Bu durumda queue tercih edilmesi daha güçlüdür.

    Queue yazıldıktan sonra API ne döndürmeli?

    İşlem henüz tamamlanmadıysa:

    completed demek doğru değildir. Örneğin: {

    • "jobId": "job_123",
    "status": "queued"

    } döndürülebilir. HTTP olarak: 202 Accepted kullanımı düşünülebilir. Client daha sonra job status’u takip eder.

    Kullanıcı progress nasıl görür?

    Örneğin: 0% queued 20% parsing 60% AI extraction 90% generating report 100% completed Worker database’de progress güncelleyebilir. UI:

    • polling,
    • SSE,

    WebSocket üzerinden alabilir. Job progress aşırı sık update edilmemeli Worker her item’da: DB update yaparsa yeni bottleneck oluşabilir. Örneğin 100.000 kayıt: 100.000 progress update yerine: her %1 veya belirli batch’lerde update yapılabilir. Job timeout ayrıca tanımlanmalı Worker’ın sonsuza kadar çalışmasına izin vermeyin. Örneğin: Report job max: 20 dk ardından: failed / timeout olabilir. AWS de Lambda timeout’unu, fonksiyonların sonsuza kadar çalışmasını önleyen safety valve olarak tanımlıyor. (AWS Dokümantasyonu) Worker/container ortamlarında da benzer üst sınırlar koymak faydalıdır.

    Queue monitoring için hangi metrikler önemli?

    Queue depth

    Kaç iş bekliyor?

    Oldest job age

    En eski iş ne kadar süredir bekliyor?

    Throughput

    Dakikada kaç iş tamamlanıyor?

    Failure rate

    Kaç job başarısız?

    Retry count

    Kaç job tekrar deneniyor?

    DLQ size

    Kaç iş tamamen başarısız?

    Processing latency

    Queue → completed süresi Backlog önemli bir alarmdır Normal: Queue: 50 job olabilir. Ama: 50 ↓ 500 ↓ 5.000 ↓ 50.000 sürekli büyüyorsa consumer kapasitesi producer’ın gerisindedir. Cloudflare concurrency dokümantasyonu da consumer autoscaling’in backlog büyüklüğü ve büyüme hızını dikkate aldığını belirtiyor. (Cloudflare Docs)

    Worker autoscaling nasıl düşünülmeli?

    Basit model:

    Backlog büyür ↓ Worker sayısı artar Ama downstream kaynakları unutmayın. Örneğin 1.000 worker açılırsa: Database connection limit External API AI rate limit çökebilir. Dolayısıyla autoscaling üst sınırı: downstream kapasitesi ile uyumlu olmalıdır.

    Queue batch processing ne zaman faydalı?

    Örneğin analytics olayları:

    1 event 1 event 1 event şeklinde ayrı ayrı database’e yazılabilir. Alternatif: 100 event ↓ batch insert daha verimli olabilir. Cloudflare Queues batching’in:

    • consumer invocation sayısını,

    external API/database write sayısını azaltabileceğini belirtiyor. (Cloudflare Docs) Ama batch hata yönetimini zorlaştırabilir 10 mesajlık batch: 1–7 başarılı 8 hata 9–10 işlenmedi olabilir. Sistem tüm batch’i retry ederse: 1–7 yeniden çalışabilir. Bu nedenle: individual ack idempotency önemlidir. Cloudflare queue consumer’ları individual message acknowledgement destekliyor; bu özellikle state-changing external API/database işlemlerinde duplicate tekrarları azaltmak için kullanılabiliyor. (Cloudflare Docs) Queue + worker mimarisinin örnek kod akışı API

    export async function POST(request: Request) {
    const user = await requireUser
    const job = await db.job.create({
    data: {
    • type: 'generate-report',
    • userId: user.id,
    • status: 'queued',
    • },

    })

    await queue.send({
    • jobId: job.id,

    })

    return Response.json(

    {

    • id: job.id,
    • status: 'queued',
    • },

    {

    • status: 202,

    } ) } Worker async function processJob(message: { jobId: string }) {

    const job = await db.job.findUnique({
    where: {
    • id: message.jobId,
    • },

    })

    if (!job) return
    if (job.status === 'completed') {
    return

    }

    await db.job.update({
    where: {
    • id: job.id,
    • },
    data: {
    • status: 'processing',
    • },

    })

    const result = await generateReport(job)
    await db.job.update({
    where: {
    • id: job.id,
    • },
    data: {
    • status: 'completed',
    • resultUrl: result.url,
    • },

    }) } Buradaki:

    if (job.status === 'completed')

    basit bir idempotency koruması örneğidir. Gerçek production implementasyonu daha güçlü transaction/locking gerektirebilir. Queue transaction problemi: Database yazıldı ama queue'ya mesaj gitmedi

    Önemli distributed-system problemi:

    1. Database job oluşturuldu ✅

    2. Queue send ❌

    Sonuç:

    job status = queued ama queue'da mesaj yok. Bunun tersi de olabilir. Bu tip kritik sistemlerde: transactional outbox event log reconciliation job gibi daha ileri pattern’ler değerlendirilebilir.

    Transactional Outbox nedir?

    Aynı database transaction içinde:

    Business record + Outbox event oluşturulur. Sonra ayrı process: outbox ↓ queue gönderir. Böylece: DB başarılı Queue başarısız arasındaki tutarsızlık riski azaltılabilir. Her proje için gerekli değildir; yüksek güvenilirlik isteyen sistemlerde değerlidir.

    Cron ile worker aynı şey mi?

    Hayır. Cron: Her 5 dakikada çalış der. Queue: İş geldiğinde çalış der. Cron şu işler için iyi olabilir: daily report nightly cleanup weekly billing Queue: user requested export webhook processing email delivery gibi event-driven işler için daha uygundur.

    Workflow engine ne zaman gerekir?

    Queue yalnızca:

    job al → çalıştır modeli için güçlüdür. Ama süreç: Step A ↓ Step B ↓ 24 saat bekle ↓ Human approval ↓ Step C ↓ failure compensation haline gelirse workflow/orchestration engine daha uygun olabilir. Örneğin: order workflow onboarding multi-step AI pipeline uzun approval süreçleri basit queue consumer’dan daha fazla orchestration isteyebilir.

    Serverless mı worker mı? 8 gerçek örnek

    1. Form submit

    Validate

    Save Respond Serverless.

    2. Form sonrası analytics

    after / waitUntil yeterli olabilir.

    3. Form sonrası kritik e-mail

    Düşük trafik:

    after değerlendirilebilir. Kritik delivery/retry gerekiyorsa: Queue.

    4. PDF raporu

    3 saniyelik küçük rapor:

    Serverless olabilir. 2–10 dakikalık karmaşık rapor: Queue + worker.

    1. 50.000 CSV kayıt import

    Queue + worker + batch.

    6. ChatGPT benzeri streaming AI

    Kullanıcı bekliyor:

    Long-running serverless streaming uygun olabilir.

    1. 500 belgeyi AI ile sınıflandırma

    Queue + workers.

    8. Payment webhook

    Request:

    validate persist event ack hızlı yapılır. Uzun fulfillment: queue üzerinden işlenebilir. Serverless + queue birlikte en güçlü model olabilir Bu nedenle karar: Serverless VS Worker değildir. Çoğu modern mimari: Serverless API + Queue + Serverless Worker olabilir. Örneğin: Next.js Route Handler ↓ Cloud Queue ↓ Worker ↓ Postgres Serverless database connection problemi de düşünülmeli Serverless concurrency hızla arttığında: Function count ↑ ↓ DB connection count ↑ oluşabilir. Modern platformlar connection pooling çözümleri sunabilir; yine de background worker concurrency’si database kapasitesiyle birlikte ayarlanmalıdır. Queue bu noktada request concurrency’sinden bağımsız bir processing limit sağlar. Maliyet karşılaştırmasında yalnızca invocation’a bakmayın Serverless: invocation CPU memory duration üzerinden ücretlenebilir. Queue: write read

    delete

    retry gibi operasyonlar ekleyebilir. Örneğin Cloudflare Queues her mesajın write/read/delete operasyonlarını ve retry’ları ayrı operasyon olarak fiyatlıyor. (Cloudflare Docs) Queue sistemi: “Kesin daha ucuz.” veya: “Kesin daha pahalı.” değildir. Doğru maliyet sorusu Şu toplam karşılaştırılmalıdır: Compute + Queue operations + Database + Storage + Retries + Operational complexity Ama queue’nun sağladığı:

    • reliability,
    • user latency,

    burst handling de hesaba katılmalıdır. Serverless karar matrisi Özellik Request Function Queue + Worker Kullanıcı sonucu bekliyor ✅ ❌/Bazen Çok kısa iş ✅ Bazen gereksiz Otomatik retry Manuel ✅ doğal Burst buffering Zayıf ✅ Independent concurrency Zayıf ✅ Progress tracking Ek geliştirme ✅ doğal Long-running batch Zayıf ✅ Operational simplicity ✅ Daha karmaşık DLQ ❌ ✅ Idempotency ihtiyacı Bazen Çok önemli Queue + Worker Geçiş Kontrol Listesi

    İş karakteristiği

    Kullanıcının sonucu request sırasında beklemesi gerekiyor mu?

    Ortalama süre ölçüldü. P95/P99 işlem süresi biliniyor.

    İş süresi input büyüklüğüne göre değişiyor mu?

    Third-party API dependency var mı?

    Retry ihtiyacı var mı?

    Burst trafik ihtimali var mı?

    Queue

    Queue tipi belirlendi. Message schema versionlandı. Payload minimum tutuldu. Hassas veri gereksiz yere queue’ya yazılmıyor. Retention süresi biliniyor. DLQ yapılandırıldı. Retry politikası belirlendi. Worker Concurrency sınırı belirlendi. Timeout belirlendi. Downstream rate limit dikkate alındı. Database kapasitesi dikkate alındı. Graceful failure davranışı var. İşler idempotent. Retry Retryable error’lar tanımlı. Permanent error’lar ayrılıyor. Backoff var. Maximum attempt var. Sonsuz retry yok. DLQ alert’i var. Idempotency Her job için unique ID var. Duplicate processing düşünülmüş. Payment/e-mail/webhook duplicate etkisi değerlendirildi. Downstream idempotency key mümkünse kullanılıyor. Job state queued processing completed failed progress attempts error saklanabiliyor. Monitoring Queue depth Oldest message Processing rate Retry rate DLQ count Failure rate Job duration izleniyor. InoviqLab teknik değerlendirmesi Bu bölüm InoviqLab değerlendirmesidir; AWS, Vercel veya Cloudflare’ın zorunlu mimari önerisi değildir. Serverless konusunda en sık yapılan hata: “Function timeout’una sığıyorsa request içinde çalışabilir.” varsayımıdır. Bu teknik olarak doğru olabilir.

    Ama mimari olarak asıl soru şudur:

    • Bu iş HTTP request lifecycle’ına ait mi?

    10 saniyelik iş bile queue'ya ait olabilir

    Örneğin: Payment provider'a webhook 10 saniyeden kısa sürebilir. Ama:

    • kesin delivery,
    • retry,

    idempotency gerekiyorsa queue güçlü adaydır. 10 dakikalık iş de request içinde kalabilir Örneğin kullanıcı: AI deep research yanıtını canlı streaming ile izliyor olabilir. Burada request’in açık olması product deneyiminin parçasıdır. Dolayısıyla: “X saniyeden uzunsa queue” şeklinde evrensel eşik vermek doğru değildir. İkinci prensip: Kullanıcı latency'si ile iş latency'sini ayırın İş: 3 dakika sürebilir. Ama kullanıcı: 300 ms içinde: “Rapor oluşturulmaya başlandı.” cevabını alabilir. Bu iki ayrı metrik: Request latency Job completion latency olarak değerlendirilmelidir. Queue bunları birbirinden ayırır. Üçüncü prensip: Queue reliability ekler ama complexity de ekler Queue sonrası artık:

    • duplicate,
    • retry,
    • DLQ,
    • monitoring,

    job state yönetmeniz gerekir. Bu nedenle: Her async iş → queue yaklaşımı gereksiz mühendislik yaratabilir. Dördüncü prensip: Background iş kritikse durable olmalı Örneğin: analytics event kaybolursa tolere edilebilir. Ama: müşterinin ödenmiş siparişini oluştur kaybolamaz. Bu durumda request sonrası basit after yerine durable queue daha doğru olabilir. Beşinci prensip: Queue kullanınca idempotency opsiyonel değildir At-least-once delivery kullanan sistemlerde: aynı mesaj tekrar gelebilir varsayımıyla kod yazılmalıdır. AWS ve Cloudflare dokümantasyonları bunu açıkça belirtmektedir. (AWS Dokümantasyonu) Özellikle: Payment Booking Email Inventory Invoice işlerinde bu kritik önemdedir. En güçlü varsayılan mimari Birçok SaaS ürünü için dengeli başlangıç modeli: Web/API → Serverless Kısa side effects → after/waitUntil Durable background work → Queue Heavy / long-running work → Worker Multi-step business process → Workflow şeklinde düşünülebilir. Her problemi tek compute modeliyle çözmeye çalışmaktan daha sağlıklıdır.

    Sonuç

    Serverless her proje için yanlış değildir. Aksine modern web ve SaaS uygulamalarında çoğu request/response işi için oldukça güçlü bir varsayılandır. Fakat: Function süresi uzadı diye bütün uzun işlemleri HTTP request’e bağlamak doğru değildir. Vercel Functions belirli plan ve runtime’larda 30 dakikalık execution’a kadar çıkabiliyor; AWS Lambda 15 dakikaya kadar çalışabiliyor. (Vercel) Buna rağmen queue + worker özellikle şu durumlarda değer kazanır: Kullanıcı işlemin bitmesini beklememeli İş retry edilmeli Trafik burst halinde gelebilir Downstream rate limit var Processing concurrency ayrı yönetilmeli İş uzun veya değişken süreli Progress izlenmeli İş kaybolmamalı En önemli mimari soru: “Bu iş serverless’ta çalışabilir mi?”

    • değil,

    “Bu iş kullanıcı request’inin bir parçası olarak mı çalışmalı?” olmalıdır.

    Kaynaklar

    • Vercel — Functions ve serverless çalışma modeli. (Vercel)
    • Vercel — Haziran 2026 itibarıyla Pro/Enterprise Node.js ve Python Functions için 30 dakikaya kadar execution süresi beta desteği. (Vercel)
    • AWS Lambda — 900 saniye / 15 dakika maksimum function timeout. (AWS Dokümantasyonu)
    • AWS SQS — Queue kullanarak distributed application bileşenlerini ayırma ve ölçekleme. (AWS Dokümantasyonu)
    • AWS SQS — At-least-once delivery ve idempotent consumer gereksinimi. (AWS Dokümantasyonu)
    • AWS SQS — Dead Letter Queue ve redrive modeli. (AWS Dokümantasyonu)
    • Cloudflare Queues — Queue ile work offloading, buffering ve batching. (Cloudflare Docs)
    • Cloudflare Queues — At-least-once delivery ve idempotency önerisi. (Cloudflare Docs)
    • Cloudflare Queues — Retry, batching ve DLQ. (Cloudflare Docs)
    • Next.js — after ile response sonrası çalışma ve süre sınırı. (Next.js)
    • Vercel — waitUntil ve background işlemlerin function timeout’una bağlı olması. (Vercel)

    Paylaş