A legtobb gyartasi alkalmazasnak olyan munkara van szuksege, ami nem fer bele a request/response ciklusba: emailek kuldese, feltoltesek feldolgozasa, AI pipeline-ok futtatasa, harmadik felek adatainak szinkronizalasa, jelentesek generalasa. A hagyomanyos valasz egy queue (Redis, SQS, RabbitMQ), egy worker flotta, egy utemezo es egy torekeny ragsasztos kod halom, ami minden deploy-nal eltorik.
A Trigger.dev ezt a stack-et egyetlen TypeScript SDK-ba sukiti. Funkciokat irsz, barhonnan hivod oket, es a platform kezeli a queueing-et, retries-et, observability-t, schedulinget es a tartos vegrehajtast. A taskok addig futnak, ameddig csak kell - nincs 10 masodperces serverless timeout, nincs elveszett munka redeploy-nal.
Miert Trigger.dev
A 2026-os valtas a tartos vegrehajtas. A workflow-knak tul kell elniuk az ujraindításokat, osszeomlasokat, deploy-okat es rate limit-eket. Valos idoben kell streamelniuk az elorehaladast a UI-ra, es szunetelniuk kell az emberi inputra. A Trigger.dev a 3-as verzioban ezekre a kovetelmenyekre lett ujjaepitve, es folyamatosan bovíti AI infrastrukturalis felulet.
A modell egyszeru: taskokat exportkent definialsz, a SDK felveszi oket, a platform utemezi es izolalt konteneerekben futtatja oket, es a run allapot megorzodik, hogy folytathasd, ujraprobalhasd es megfigyelhesd.
Kezdes
Inicializaltassuk projektet
npx trigger.dev@latest login npx trigger.dev@latest init
Ez letrehoz egy trigger.config.ts fajlt es egy trigger/ konyvtarat pelda taskokkal. A config fajl a projekt igazsag forrasa: melyik konyvtarak tartalmaznak taskokat, build beallitasokat, lifecycle hookokat es runtime opciokat.
// trigger.config.ts import { defineConfig } from "@trigger.dev/sdk"; export default defineConfig({ project: "proj_abc123", runtime: "node", logLevel: "log", maxDuration: 3600, retries: { enabledInDev: true, default: { maxAttempts: 3, factor: 2, minTimeoutInMs: 1000, maxTimeoutInMs: 30_000, }, }, dirs: ["./trigger"], });
Futtass taskokat helyileg
npx trigger.dev@latest dev
A dev szerver csatlakozik a felhohoz, regisztralja a taskjaidat es streameli a runokat a helyi kododon keresztul. Tortest pontokat allitasz be a szerkesztodben, es valodi triggerekre talalsz - ugyanaz a ciklus, amit barmilyen normalis Node.js projektben hasznalnal.
Egy Task definialasa
A task egy exportalt objektum egyedi id-val es egy run funkcioval. A SDK megvizsgalja az exporokat a dirs-en at, es automatikusan regisztralja oket.
// trigger/send-welcome-email.ts import { task } from "@trigger.dev/sdk"; import { Resend } from "resend"; const resend = new Resend(process.env.RESEND_API_KEY); export const sendWelcomeEmail = task({ id: "send-welcome-email", retry: { maxAttempts: 5, factor: 1.8, minTimeoutInMs: 500, maxTimeoutInMs: 30_000, }, run: async (payload: { email: string; name: string }) => { const { data, error } = await resend.emails.send({ from: "hello@spinny.dev", to: payload.email, subject: `Welcome, ${payload.name}`, html: `<p>Glad you are here, ${payload.name}.</p>`, }); if (error) throw error; return { messageId: data?.id }; }, });
Harom dolog, amire figyelni kell:
- Nincs timeout a run torzsben. A platform a
maxDurationconfigon keresztul kezeli a vegrehajtasi idot, nem a runtime-on. - A throws-ok retries-ek. A SDK elkapja a kiveteleket es ujrafuttat exponencialis backoff-fal a
retrypolicy szerint. - A visszateresi ertek megorzodik. Mas taskok es a frontended barhonnan olvashatja a
run.output-ot.
Taskok triggerelese
Egy taskot hivsz a backendrol, az API route-jaibol vagy egy masik taskbol.
import { sendWelcomeEmail } from "@/trigger/send-welcome-email"; const handle = await sendWelcomeEmail.trigger( { email: "user@example.com", name: "Alex" }, { idempotencyKey: `welcome-${userId}`, concurrencyKey: `tenant-${tenantId}`, queue: { name: "emails", concurrencyLimit: 50 }, delay: "30s", ttl: "10m", } ); console.log(handle.id); // run_xyz - hasznald a kovetesere vagy a halados megjelenitesere
Az opciok sok viselkedest oldanak fel egy hivasban:
idempotencyKey- ha mar letezik egy run ugyanazzal a kulccsal, a SDK a meglevo handle-t adja vissza ahelyett, hogy duplazna a munkat.concurrencyKey- serializalja a kulcsot megosztó runokat, hogy ne lepd tul a per-tenant rate limit-et.queue.concurrencyLimit- globalis cap a queue-hoz minden kulcson at.delay- a runot egy jovobeni idore utemezi.ttl- ha a run addigra nem indult el, automatikusan lejar.
Batch trigger
Fan-out workloadokhoz a batchTrigger legfeljebb 500 elemet fogad el hivasonkent es egy runot keszit elemenkent.
await sendWelcomeEmail.batchTrigger( newUsers.map((u) => ({ payload: { email: u.email, name: u.name }, options: { idempotencyKey: `welcome-${u.id}` }, })) );
Utemezett Taskok
A cron job-ok elsoosztalyu deklaraciokka valnak. Maga a schedule egy kulonallo objektum, amit tobbszor csatolhatsz egy taskhoz.
// trigger/daily-digest.ts import { schedules } from "@trigger.dev/sdk"; export const dailyDigest = schedules.task({ id: "daily-digest", cron: "0 9 * * *", run: async (payload) => { console.log("Scheduled at:", payload.timestamp); console.log("Last run:", payload.lastTimestamp); console.log("Timezone:", payload.timezone); console.log("Next 5 runs:", payload.upcoming); await sendDigestForDate(payload.timestamp); }, });
Per-tenant schedule-ekhez - mondjuk egy cron ugyfelenkent - dinamikusan letrehozod oket a management API-n keresztul.
import { schedules } from "@trigger.dev/sdk"; await schedules.create({ task: "daily-digest", cron: "0 9 * * *", timezone: "America/New_York", externalId: `customer_${customerId}`, deduplicationKey: `digest-${customerId}`, });
A deduplicationKey idempotensse teszi a hivast: ugyanazon kod ujrafuttatasa deploy-kor nem stackeli a duplikalt schedule-eket.
Queues, Konkurencia es Idempotencia
Harom primitiv lefedi a rate-limiting es rendezesi igenyek nagy reszet.
Egy gyakori minta: egy queue tenantonkent kis per-key konkurenciaval a vendor rate limit tiszteletben tartasahoz, plusz egy idempotencia kulcs a retries biztossagahoz.
await syncShopifyOrders.trigger( { shopId }, { queue: { name: `shopify-${shopId}`, concurrencyLimit: 2 }, concurrencyKey: shopId, idempotencyKey: `sync-${shopId}-${Date.now() / 60_000 | 0}`, } );
Varakozas es hosszan futo munka
A taskok megallhatnak anelkul, hogy tartanak egy kapcsolatot vagy egetnenek compute-ot. A platform megorzi az allapotot es folytatja a funkciot, amikor a varakozas befejezodik.
import { wait } from "@trigger.dev/sdk"; export const onboarding = task({ id: "onboarding", run: async (payload: { userId: string }) => { await sendWelcomeEmail.triggerAndWait({ userId: payload.userId }); await wait.for({ days: 1 }); await sendTipsEmail.trigger({ userId: payload.userId }); await wait.until({ date: oneWeekFromSignup(payload.userId) }); await sendUpgradeOffer.trigger({ userId: payload.userId }); }, });
A triggerAndWait a killer feature: kivaltja a gyermek taskot es felfuggeszti a szuolot, amig a gyermek befejezodik. A taskokat async funkciokent komponalod, de az orchestralas tartoasan fut napokon vagy heteken at.
Human-in-the-loop a wait.forToken-nel
Approval folyamatokhoz es AI gate-ekhez a wait.forToken szunetel, amig az alkalmazasod vissza nem hív egy eredmennyel.
import { task, wait } from "@trigger.dev/sdk"; export const publishPost = task({ id: "publish-post", run: async (payload: { draftId: string }) => { const draft = await generateAIContent(payload.draftId); const token = await wait.createToken({ timeout: "7d" }); await notifyEditor({ draftId: draft.id, token: token.id }); const decision = await wait.forToken<{ approved: boolean; notes?: string }>( token.id ); if (decision.approved) { return await publish(draft); } return await applyFeedback(draft, decision.notes); }, });
A szerkeszto megnyit egy UI-t, atnezi a piszkozatot, ratallintat a Jovahagyas-ra es a backended befejezi a tokent. A task onnan folytatodik, ahol abbahagyta - meg akkor is, ha orak vagy napok teltek el.
Lifecycle Hookok
Csatolhatsz init, onStart, onSuccess es onFailure-t egy taskhoz vagy globalisan a trigger.config.ts-ben. Hasznald oket tracinghez, error reportinghez es megosztott setuphoz.
// trigger.config.ts export default defineConfig({ // ... init: async () => { Sentry.init({ dsn: process.env.SENTRY_DSN }); }, onFailure: async ({ error, ctx }) => { Sentry.captureException(error, { tags: { taskId: ctx.task.id, runId: ctx.run.id }, }); }, });
Az init egyszer fut worker containerenkent boot-kor, nem runonkent, ezert ez a megfelelo hely a kliensek es poolok beallitasara.
Realtime a frontenden
A Trigger.dev publikalja a run allapot valtozasait - status, metadata, output - egy streaming API-n keresztul. A React hookok feliratkoznak erre a streamre es automatikusan ujrarenderelnek.
// trigger/process-video.ts import { task, metadata } from "@trigger.dev/sdk"; export const processVideo = task({ id: "process-video", run: async (payload: { videoId: string }) => { metadata.set("stage", "transcoding"); await transcode(payload.videoId); metadata.set("stage", "thumbnails"); await generateThumbnails(payload.videoId); metadata.set("stage", "uploading"); const url = await uploadToCDN(payload.videoId); return { url }; }, });
// components/VideoStatus.tsx "use client"; import { useRealtimeRun } from "@trigger.dev/react-hooks"; import type { processVideo } from "@/trigger/process-video"; export function VideoStatus({ runId, publicAccessToken, }: { runId: string; publicAccessToken: string; }) { const { run, error } = useRealtimeRun<typeof processVideo>(runId, { accessToken: publicAccessToken, }); if (error) return <p>Error: {error.message}</p>; if (!run) return <p>Loading...</p>; return ( <div> <p>Status: {run.status}</p> <p>Stage: {String(run.metadata?.stage ?? "queued")}</p> {run.output?.url && <video src={run.output.url} controls />} </div> ); }
Generalod a public access tokent a szerver oldalan, egy specifikus runra scoped, es elkuldod a kliensnek. A hook kezeli az autht, az ujra csatlakozast es az inkrementalis frissiteseket.
Trigger-and-subscribe-hoz egy lepesben:
import { useRealtimeTaskTrigger } from "@trigger.dev/react-hooks"; const { submit, run, isLoading } = useRealtimeTaskTrigger<typeof processVideo>( "process-video", { accessToken: publicAccessToken } ); <button onClick={() => submit({ videoId })} disabled={isLoading}> Process video </button>;
AI Agentek es Streaming
A Trigger.dev nepszeru runtime-ma valt az AI agentek szamara, mert ugyanazok a primitivek - tartos vegrehajtas, retries, varakozasok, valos ideju metadata, human-in-the-loop - pontosan azok, amikre az agenseknek szuksegunk van. Tokeneket streamelsz egy modell szolgaltatotol a metadata-ba, mialatt a run zajlik, a frontend elve renderelje oket, es a run tuleli a hosszan futo tool callokat anelkul, hogy egetne egy serverless timeoutot.
import { task, metadata } from "@trigger.dev/sdk"; import { streamText } from "ai"; import { anthropic } from "@ai-sdk/anthropic"; export const researchAgent = task({ id: "research-agent", maxDuration: 1800, run: async (payload: { question: string }) => { const result = streamText({ model: anthropic("claude-opus-4-7"), system: "You are a research assistant. Use the web.", prompt: payload.question, tools: { webSearch }, }); let fullText = ""; for await (const chunk of result.textStream) { fullText += chunk; metadata.set("partial", fullText); } return { answer: fullText, usage: await result.usage }; }, });
A frontend a useRealtimeRun-ot hasznalja es olvassa a run.metadata.partial-t a streaming valasz renderelesere, ugyanugy, mintha egy chat completiont rendererel - kiveve, hogy ez tuleli egy teljes oldal ujratoltest.
Deployment
A deployok lefordijak a taskjaidat egy verziozott bundle-be, kepetnek egy konteneert es atomikusan atvaltjak a forgalmat. A regi in-flight runok tovabbra is hasznaljak az elozo verziot.
npx trigger.dev@latest deploy --env prod
CI-ben tipikusan ezt ahhoz a workflow-hoz csatolod, amelyik a kuldi az alkalmazasod:
# .github/workflows/deploy.yml - name: Deploy Trigger.dev env: TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }} run: npx trigger.dev@latest deploy --env prod
Preview kornyezetekhez add at a --env preview --branch ${{ github.head_ref }}-ot es a Trigger.dev letrehoz egy izolalt kornyezetet branchenkent, tukrozve azt, ahogy a Vercel kezeli a preview deploymenteket.
Self-Hosting vs Cloud
A Trigger.dev nyilt forraskodu az Apache 2.0 licenc alatt. Self-hostolhatsz barmilyen container platformon (Docker Compose, Kubernetes, Fly.io) vagy hasznalhatod a managed cloudot a trigger.dev-en.
| Aspektus | Cloud | Self-hosted |
|---|---|---|
| Setup | Regisztracio, init futtatasa | docker-compose vagy Helm chart futtatasa |
| Scaling | Automatikus | A te felelosseged |
| Pricing | Per run + per compute | Csak infra koltseg |
| Compliance | SOC 2 | Amit a kornyezet biztosit |
| Legjobb | Legtobb csapatnak | Szigoru data residency, custom infra |
Az SDK es CLI azonosak a modok kozott - egy profile flag-et valtoztatsz es a sajat instance-edre mutatsz.
Best Practices
1. Tartsd a payloadokat kicsiknek es szerializalhatonak
Add at az ID-kat es referenciakat, ne a teljes objektumokat. Hivd be az adatokat a tasken belul. Ez kicsiben tartja a queue-t, olcsova teszi a payloadok logolását es lehetove teszi, hogy az adat forrast valtoztasd anelkul, hogy ujra triggerelnel.
2. Idempotencia kulcsok minden kulso hivason
Kombinald az idempotencyKey-t a task triggeren a vendor API-k (Stripe, OpenAI, stb.) idempotencia kulcsaival. A retries end-to-end biztonsagosak lesznek.
3. Hasznald a triggerAndWait-et orchestraciohoz, nem a triggerek Promise.all-jat
Egy szuolo, amelyik triggerAndWait-et hiv, tartoasan komponalja a gyermek taskokat. Egy szuolo, amelyik triggerel es azonnal feloldoja, elveszti a lanc megfigyelhetoseget.
4. Tageld a runokat
Adj tags-eket a triggereknek (tags: ["user:123", "feature:onboarding"]), hogy szurhesd a dashboardot es a management API-t uzleti dimenziok szerint.
5. Tartsd az init-et idempotensnek
Minden cold startkor fut. Kerüld a migracikat vagy egyszeri side effecteket ott.
Kovetkezte tes
A Trigger.dev eltunteti azokat a munka kategoriakat, amelyek korabban szukseges voltak ahhoz, hogy egy job rendszert epitsel a nullarol. Async TypeScriptet irsz, barhonnan hivod es a platform ad neked tartos vegrehajtast, schedulinget, queueket, retries-eket, valos ideju frissiteseket es human-in-the-loop mintakat dobozbol.
Ugyanaz a felulet, amelyik egy ejszakai cront hajt, az a felulet, amelyik egy multi-step AI agentet hajt, ami streamel a frontendre es szunetel a review-ert. Ez a konvergencia teszi a frameworkot 2026-ban komoly pillantasra meltova, akar egy SaaS-t mukodtetsz, amelyik megbizhato hatter munkat igenyel, akar AI funkciokat szallitasz, amelyek tulelik a serverless timeoutot.
Kezdes Checklist:
- Regisztralj a trigger.dev-en vagy futtasd a self-hosted Docker stacket
npx trigger.dev@latest inita projektben- Definiald az elso taskodat a
task({ id, run })-nel- Triggereld az API-dbol es nezd a runot a dashboardon
- Adj hozza
idempotencyKey-t esconcurrencyKey-t a produkcios biztonsaghoz- Csatold a
useRealtimeRun-t egy status komponenshez- Deployolj a
trigger.dev deploy --env prod-dal CI-bol