Construire des tâches de fond en production avec Trigger.dev v3 et Next.js

Les applications web modernes doivent gérer des opérations qui ne devraient pas bloquer la requête utilisateur — envoyer des emails, traiter des images, synchroniser des données avec des API tierces, générer des rapports ou exécuter des pipelines IA. Sans système de tâches de fond, vous êtes coincé avec des solutions fragiles : des hacks setTimeout, des timeouts de fonctions edge, ou le déploiement de serveurs workers séparés.
Trigger.dev v3 résout ce problème en fournissant un framework de tâches de fond natif TypeScript qui exécute vos tâches sur une infrastructure gérée avec des retries intégrés, du logging et de la supervision. Vous écrivez des tâches comme de simples fonctions TypeScript, vous les déclenchez depuis vos routes API ou Server Actions Next.js, et Trigger.dev gère le reste — exécution, retries, planification et monitoring.
Dans ce tutoriel, vous allez construire un système d'automatisation d'onboarding utilisateur — quand un nouvel utilisateur s'inscrit, un workflow de fond envoie un email de bienvenue, génère un avatar personnalisé, synchronise l'utilisateur avec un CRM, et planifie un email de suivi pour 3 jours plus tard. En cours de route, vous maîtriserez les tâches Trigger.dev v3, la gestion des erreurs, les workflows multi-étapes, les tâches planifiées et le déploiement en production.
Prérequis
Avant de commencer, assurez-vous d'avoir :
- Node.js 20+ installé
- Un compte Trigger.dev gratuit — inscrivez-vous sur le site Trigger.dev
- Des connaissances de base en React et TypeScript
- Une familiarité avec Next.js App Router (routes API, Server Actions)
- Un éditeur de code (VS Code recommandé)
Ce que vous allez construire
Un système d'automatisation d'onboarding avec :
- Tâche d'email de bienvenue — envoie un email formaté quand un utilisateur s'inscrit
- Tâche de génération d'avatar — crée un avatar personnalisé via une API externe
- Tâche de synchronisation CRM — pousse les données du nouvel utilisateur vers un CRM externe
- Workflow d'onboarding multi-étapes — orchestre toutes les tâches en séquence avec gestion des erreurs
- Suivi planifié — envoie un email de suivi 3 jours après l'inscription
- Cron job — digest quotidien des nouvelles inscriptions pour l'équipe admin
- Observabilité complète — logs, exécutions et erreurs visibles dans le dashboard Trigger.dev
Étape 1 : Créer le projet Next.js
Initialisez un nouveau projet Next.js 15 :
npx create-next-app@latest trigger-onboarding --typescript --tailwind --eslint --app --src-dir --use-npm
cd trigger-onboardingInstallez le SDK Trigger.dev et le CLI :
npm install @trigger.dev/sdk
npm install -D trigger.devLe package @trigger.dev/sdk fournit l'API runtime pour définir et déclencher des tâches. Le CLI trigger.dev gère le développement local et le déploiement.
Étape 2 : Initialiser Trigger.dev
Exécutez la commande init pour configurer Trigger.dev dans votre projet :
npx trigger.dev@latest initCette commande effectue plusieurs actions :
- Crée un fichier
trigger.config.tsà la racine du projet - Crée un répertoire
src/trigger/pour vos fichiers de tâches - Ajoute la référence du projet et la clé API dans
.env.local - Met à jour
package.jsonavec les scripts dev et deploy
Votre trigger.config.ts devrait ressembler à ceci :
import { defineConfig } from "@trigger.dev/sdk/v3";
export default defineConfig({
project: "proj_your_project_id",
runtime: "node",
logLevel: "log",
retries: {
enabledInDev: true,
default: {
maxAttempts: 3,
minTimeoutInMs: 1000,
maxTimeoutInMs: 10000,
factor: 2,
},
},
dirs: ["src/trigger"],
});La configuration retries est importante — elle définit une politique de retry par défaut pour toutes les tâches. Quand une tâche échoue, Trigger.dev la réessaie jusqu'à 3 fois avec un backoff exponentiel (délais de 1s, 2s, 4s).
Étape 3 : Créer votre première tâche — Email de bienvenue
Créez un fichier src/trigger/welcome-email.ts :
import { task, logger } from "@trigger.dev/sdk/v3";
export interface WelcomeEmailPayload {
userId: string;
email: string;
name: string;
}
export const sendWelcomeEmail = task({
id: "send-welcome-email",
retry: {
maxAttempts: 5,
},
run: async (payload: WelcomeEmailPayload) => {
logger.info("Sending welcome email", {
userId: payload.userId,
email: payload.email,
});
const response = await fetch("https://api.resend.com/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RESEND_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "welcome@yourapp.com",
to: payload.email,
subject: `Welcome to Our App, ${payload.name}!`,
html: `
<h1>Welcome, ${payload.name}!</h1>
<p>We are excited to have you on board.</p>
<p>Here are some things you can do to get started:</p>
<ul>
<li>Complete your profile</li>
<li>Explore the dashboard</li>
<li>Connect your first integration</li>
</ul>
`,
}),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Failed to send email: ${error}`);
}
const result = await response.json();
logger.info("Welcome email sent successfully", {
emailId: result.id,
});
return { emailId: result.id, sentAt: new Date().toISOString() };
},
});Points clés à noter :
task()définit une tâche de fond avec uniduniqueloggerfournit un logging structuré visible dans le dashboard Trigger.devretryremplace la politique de retry par défaut — les emails sont critiques, donc on réessaie 5 fois- Lancer une erreur déclenche automatiquement un retry
- La valeur de retour est stockée et visible dans le dashboard pour le débogage
Étape 4 : Créer la tâche de génération d'avatar
Créez src/trigger/generate-avatar.ts :
import { task, logger } from "@trigger.dev/sdk/v3";
export interface AvatarPayload {
userId: string;
name: string;
}
export const generateAvatar = task({
id: "generate-avatar",
retry: {
maxAttempts: 3,
},
run: async (payload: AvatarPayload) => {
logger.info("Generating avatar", { userId: payload.userId });
const initials = payload.name
.split(" ")
.map((n) => n[0])
.join("")
.toUpperCase();
const seed = encodeURIComponent(payload.name);
const avatarUrl = `https://api.dicebear.com/8.x/initials/svg?seed=${seed}&chars=${initials.length}`;
const response = await fetch(avatarUrl);
if (!response.ok) {
throw new Error(`Avatar generation failed: ${response.statusText}`);
}
const svgContent = await response.text();
const storedUrl = `/avatars/${payload.userId}.svg`;
logger.info("Avatar generated", {
userId: payload.userId,
url: storedUrl,
});
return { avatarUrl: storedUrl, svgSize: svgContent.length };
},
});Étape 5 : Créer la tâche de synchronisation CRM
Créez src/trigger/sync-crm.ts :
import { task, logger } from "@trigger.dev/sdk/v3";
export interface CrmSyncPayload {
userId: string;
email: string;
name: string;
signupDate: string;
}
export const syncToCrm = task({
id: "sync-to-crm",
retry: {
maxAttempts: 4,
minTimeoutInMs: 2000,
maxTimeoutInMs: 30000,
factor: 3,
},
run: async (payload: CrmSyncPayload) => {
logger.info("Syncing user to CRM", {
userId: payload.userId,
email: payload.email,
});
const crmResponse = await fetch(
`${process.env.CRM_API_URL}/contacts`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CRM_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
email: payload.email,
name: payload.name,
properties: {
signup_date: payload.signupDate,
source: "web_app",
lifecycle_stage: "subscriber",
},
}),
}
);
if (!crmResponse.ok) {
const error = await crmResponse.text();
logger.error("CRM sync failed", { error });
throw new Error(`CRM sync failed: ${error}`);
}
const contact = await crmResponse.json();
logger.info("CRM sync completed", {
crmContactId: contact.id,
});
return { crmContactId: contact.id };
},
});Notez la configuration de retry ici — les API CRM peuvent être instables, donc on utilise un backoff plus agressif (factor: 3) avec un timeout maximum de 30 secondes.
Étape 6 : Construire le workflow d'onboarding multi-étapes
Maintenant la partie puissante — orchestrer toutes les tâches en un seul workflow. Créez src/trigger/onboarding-workflow.ts :
import { task, logger, wait } from "@trigger.dev/sdk/v3";
import { sendWelcomeEmail } from "./welcome-email";
import { generateAvatar } from "./generate-avatar";
import { syncToCrm } from "./sync-crm";
export interface OnboardingPayload {
userId: string;
email: string;
name: string;
}
export const onboardingWorkflow = task({
id: "onboarding-workflow",
retry: {
maxAttempts: 1,
},
run: async (payload: OnboardingPayload) => {
logger.info("Starting onboarding workflow", {
userId: payload.userId,
});
// Étape 1 : Envoyer l'email de bienvenue et générer l'avatar en parallèle
const [emailResult, avatarResult] = await Promise.all([
sendWelcomeEmail.triggerAndWait({
userId: payload.userId,
email: payload.email,
name: payload.name,
}),
generateAvatar.triggerAndWait({
userId: payload.userId,
name: payload.name,
}),
]);
logger.info("Email and avatar completed", {
emailOk: emailResult.ok,
avatarOk: avatarResult.ok,
});
// Étape 2 : Synchroniser avec le CRM
const crmResult = await syncToCrm.triggerAndWait({
userId: payload.userId,
email: payload.email,
name: payload.name,
signupDate: new Date().toISOString(),
});
logger.info("CRM sync completed", { crmOk: crmResult.ok });
// Étape 3 : Planifier un email de suivi dans 3 jours
const followUpHandle = await sendFollowUpEmail.trigger(
{
userId: payload.userId,
email: payload.email,
name: payload.name,
},
{
delay: "3d",
}
);
logger.info("Follow-up email scheduled", {
followUpId: followUpHandle.id,
});
return {
emailResult: emailResult.ok ? emailResult.output : null,
avatarResult: avatarResult.ok ? avatarResult.output : null,
crmResult: crmResult.ok ? crmResult.output : null,
followUpScheduled: followUpHandle.id,
};
},
});
const sendFollowUpEmail = task({
id: "send-follow-up-email",
retry: {
maxAttempts: 5,
},
run: async (payload: OnboardingPayload) => {
logger.info("Sending follow-up email", {
userId: payload.userId,
});
const response = await fetch("https://api.resend.com/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RESEND_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "hello@yourapp.com",
to: payload.email,
subject: `How's it going, ${payload.name}?`,
html: `
<h1>Hey ${payload.name}!</h1>
<p>You signed up 3 days ago — how is everything going?</p>
<p>Need help getting started? Reply to this email and we will help!</p>
`,
}),
});
if (!response.ok) {
throw new Error(`Follow-up email failed: ${await response.text()}`);
}
return { sent: true };
},
});Ce workflow démontre plusieurs fonctionnalités puissantes de Trigger.dev :
triggerAndWait()— déclenche une tâche enfant et attend son achèvement, retournant le résultatPromise.all()— exécute des tâches indépendantes en parallèle pour de meilleures performancestrigger()avecdelay— planifie une tâche pour le futur (3 jours plus tard)- Orchestration de workflow — une tâche parent coordonne plusieurs tâches enfants
Étape 7 : Ajouter un cron job planifié
Créez src/trigger/daily-digest.ts pour un digest admin quotidien :
import { schedules, logger } from "@trigger.dev/sdk/v3";
export const dailySignupDigest = schedules.task({
id: "daily-signup-digest",
cron: "0 9 * * *", // Chaque jour à 9h00 UTC
run: async () => {
logger.info("Running daily signup digest");
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const newUsers = await fetchNewUsers(yesterday);
if (newUsers.length === 0) {
logger.info("No new signups yesterday");
return { sent: false, reason: "no_new_signups" };
}
const response = await fetch("https://api.resend.com/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RESEND_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "reports@yourapp.com",
to: "admin@yourapp.com",
subject: `Daily Signup Digest — ${newUsers.length} new users`,
html: `
<h1>Daily Signup Report</h1>
<p>${newUsers.length} new users signed up yesterday:</p>
<table>
<tr><th>Name</th><th>Email</th><th>Time</th></tr>
${newUsers
.map(
(u) =>
`<tr><td>${u.name}</td><td>${u.email}</td><td>${u.createdAt}</td></tr>`
)
.join("")}
</table>
`,
}),
});
if (!response.ok) {
throw new Error(`Digest email failed: ${await response.text()}`);
}
logger.info("Digest sent", { userCount: newUsers.length });
return { sent: true, userCount: newUsers.length };
},
});
async function fetchNewUsers(since: Date) {
return [
{
name: "Alice",
email: "alice@example.com",
createdAt: since.toISOString(),
},
];
}La fonction schedules.task() crée une tâche déclenchée par cron. L'expression cron 0 9 * * * signifie "chaque jour à 9h00 UTC".
Étape 8 : Déclencher les tâches depuis Next.js
Connectez maintenant le workflow à votre application Next.js. Créez une route API dans src/app/api/signup/route.ts :
import { NextRequest, NextResponse } from "next/server";
import { tasks } from "@trigger.dev/sdk/v3";
import type { onboardingWorkflow } from "@/trigger/onboarding-workflow";
export async function POST(request: NextRequest) {
const body = await request.json();
const { email, name, userId } = body;
if (!email || !name || !userId) {
return NextResponse.json(
{ error: "Missing required fields" },
{ status: 400 }
);
}
const handle = await tasks.trigger<typeof onboardingWorkflow>(
"onboarding-workflow",
{
userId,
email,
name,
}
);
return NextResponse.json({
message: "Signup successful! Onboarding started.",
runId: handle.id,
});
}Point clé : tasks.trigger() retourne immédiatement — il n'attend pas que la tâche de fond se termine. L'utilisateur obtient une réponse instantanée pendant que le workflow d'onboarding s'exécute de manière asynchrone.
Vous pouvez également déclencher des tâches depuis les Server Actions. Créez src/app/actions.ts :
"use server";
import { tasks } from "@trigger.dev/sdk/v3";
import type { onboardingWorkflow } from "@/trigger/onboarding-workflow";
export async function signupAction(formData: FormData) {
const email = formData.get("email") as string;
const name = formData.get("name") as string;
const userId = crypto.randomUUID();
const handle = await tasks.trigger<typeof onboardingWorkflow>(
"onboarding-workflow",
{ userId, email, name }
);
return { success: true, runId: handle.id };
}Étape 9 : Construire un formulaire d'inscription simple
Créez src/app/page.tsx :
"use client";
import { useState } from "react";
import { signupAction } from "./actions";
export default function SignupPage() {
const [status, setStatus] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
async function handleSubmit(formData: FormData) {
setLoading(true);
try {
const result = await signupAction(formData);
setStatus(
`Inscription réussie ! Onboarding en cours : ${result.runId}`
);
} catch (error) {
setStatus("Une erreur est survenue. Veuillez réessayer.");
} finally {
setLoading(false);
}
}
return (
<main className="flex min-h-screen items-center justify-center bg-gray-50">
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
<h1 className="mb-6 text-2xl font-bold text-gray-900">
Inscription
</h1>
<form action={handleSubmit} className="space-y-4">
<div>
<label
htmlFor="name"
className="block text-sm font-medium text-gray-700"
>
Nom
</label>
<input
type="text"
id="name"
name="name"
required
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
/>
</div>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-gray-700"
>
Email
</label>
<input
type="email"
id="email"
name="email"
required
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
/>
</div>
<button
type="submit"
disabled={loading}
className="w-full rounded-md bg-blue-600 px-4 py-2 text-white hover:bg-blue-700 disabled:opacity-50"
>
{loading ? "Inscription en cours..." : "S'inscrire"}
</button>
</form>
{status && (
<p className="mt-4 rounded bg-green-50 p-3 text-sm text-green-700">
{status}
</p>
)}
</div>
</main>
);
}Étape 10 : Lancer le serveur de développement
Démarrez le serveur Next.js et le worker Trigger.dev :
# Terminal 1 : Next.js
npm run dev
# Terminal 2 : Worker Trigger.dev
npx trigger.dev@latest devLa commande Trigger.dev dev se connecte au cloud Trigger.dev et exécute vos tâches localement. Ouvrez le dashboard Trigger.dev pour voir les logs en temps réel.
Testez le flux :
- Ouvrez votre app sur
http://localhost:3000 - Remplissez le formulaire et soumettez
- Observez le dashboard Trigger.dev — vous verrez le workflow démarrer, les tâches email et avatar s'exécuter en parallèle, puis la synchro CRM, et enfin l'email de suivi planifié pour dans 3 jours
Étape 11 : Gestion des erreurs et stratégies de retry
Trigger.dev offre un contrôle granulaire sur la gestion des erreurs. Améliorons la tâche email :
import { task, logger, retry } from "@trigger.dev/sdk/v3";
export const sendWelcomeEmailV2 = task({
id: "send-welcome-email-v2",
retry: {
maxAttempts: 5,
minTimeoutInMs: 1000,
maxTimeoutInMs: 60000,
factor: 2,
},
onFailure: async (payload, error, params) => {
logger.error("Welcome email permanently failed", {
userId: payload.userId,
error: error.message,
attempts: params.attemptCount,
});
await fetch(process.env.SLACK_WEBHOOK_URL!, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: `Failed to send welcome email to ${payload.email} after ${params.attemptCount} attempts: ${error.message}`,
}),
});
},
run: async (payload: WelcomeEmailPayload) => {
// Implémentation de la tâche...
},
});Le callback onFailure ne s'exécute qu'après épuisement de tous les retries — c'est votre dernière chance de gérer l'échec.
Vous pouvez aussi utiliser retry.onThrow pour un contrôle fin des retries dans une tâche :
run: async (payload) => {
const result = await retry.onThrow(
async () => {
const res = await fetch("https://flaky-api.com/data");
if (!res.ok) throw new Error("API call failed");
return res.json();
},
{ maxAttempts: 3, randomize: true }
);
logger.info("Got data", { result });
};Étape 12 : Ajouter des métadonnées et des tags
Les tags et métadonnées rendent les tâches recherchables et filtrables dans le dashboard :
import { task, logger, metadata, tags } from "@trigger.dev/sdk/v3";
export const processOrder = task({
id: "process-order",
run: async (payload: { orderId: string; userId: string; amount: number }) => {
tags.add("order", payload.orderId);
tags.add("user", payload.userId);
metadata.set("orderAmount", payload.amount);
metadata.set("currency", "USD");
metadata.set("status", "processing");
// ... traitement de la commande ...
metadata.set("status", "completed");
return { processed: true };
},
});Étape 13 : Opérations par lots avec batchTrigger
Quand vous devez traiter plusieurs éléments, utilisez le déclenchement par lots :
import { tasks } from "@trigger.dev/sdk/v3";
import type { sendWelcomeEmail } from "@/trigger/welcome-email";
export async function sendBulkEmails(
users: Array<{ userId: string; email: string; name: string }>
) {
const handle = await tasks.batchTrigger<typeof sendWelcomeEmail>(
"send-welcome-email",
users.map((user) => ({
payload: user,
}))
);
return {
batchId: handle.batchId,
runCount: handle.runs.length,
};
}Trigger.dev traite les éléments par lots avec une concurrence contrôlée, évitant de surcharger les services en aval.
Étape 14 : Variables d'environnement et configuration
Ajoutez vos variables dans .env.local :
# Trigger.dev
TRIGGER_SECRET_KEY=tr_dev_your_secret_key
# Email (Resend)
RESEND_API_KEY=re_your_api_key
# CRM
CRM_API_URL=https://api.your-crm.com
CRM_API_KEY=your_crm_key
# Notifications
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/your/webhookPour la production, ajoutez ces mêmes variables dans le dashboard Trigger.dev sous les paramètres du projet.
Étape 15 : Déployer en production
Déployez vos tâches sur le cloud Trigger.dev :
npx trigger.dev@latest deployCette commande :
- Bundle votre code de tâches
- Le téléverse sur le cloud Trigger.dev
- Rend vos tâches disponibles pour le déclenchement en production
Pour l'intégration CI/CD, ajoutez la commande deploy à votre pipeline :
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy-trigger:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx trigger.dev@latest deploy
env:
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}Étape 16 : Surveiller et déboguer
Le dashboard Trigger.dev offre une observabilité complète :
- Liste des exécutions — voir toutes les exécutions de tâches avec statut, durée et horodatage
- Détails d'exécution — voir les logs, le payload, la sortie et l'historique des retries
- Trace du workflow — visualiser les workflows multi-étapes avec les relations parent-enfant
- Erreurs — filtrer et rechercher les exécutions échouées avec les stack traces complètes
- Planifications — gérer et surveiller les cron jobs
Tester votre implémentation
Pour vérifier que tout fonctionne :
- Démarrez le serveur dev et le worker Trigger.dev dans deux terminaux
- Soumettez le formulaire — vous devriez voir une réponse instantanée
- Vérifiez le dashboard Trigger.dev — le workflow devrait montrer toutes les étapes
- Testez la gestion des erreurs — cassez temporairement une clé API et vérifiez les retries
- Vérifiez le cron job — il devrait apparaître dans l'onglet Planifications
Dépannage
Les tâches n'apparaissent pas dans le dashboard :
Assurez-vous que npx trigger.dev@latest dev est en cours d'exécution. Vérifiez que trigger.config.ts pointe vers les bons répertoires.
Les tâches échouent avec "Module not found" : Trigger.dev bundle les tâches séparément de Next.js. Assurez-vous que tous les imports dans les fichiers de tâches sont autonomes.
Les retries ne fonctionnent pas en développement :
Configurez enabledInDev: true dans la configuration retries de trigger.config.ts.
Les variables d'environnement ne sont pas disponibles :
En développement, les tâches lisent depuis .env.local. En production, configurez les variables dans le dashboard Trigger.dev.
Structure du projet
Voici la structure finale du projet :
trigger-onboarding/
src/
app/
api/
signup/
route.ts # Route API pour déclencher l'onboarding
actions.ts # Server Action pour la soumission du formulaire
page.tsx # Interface du formulaire d'inscription
trigger/
welcome-email.ts # Tâche d'email de bienvenue
generate-avatar.ts # Tâche de génération d'avatar
sync-crm.ts # Tâche de synchronisation CRM
onboarding-workflow.ts # Orchestrateur de workflow multi-étapes
daily-digest.ts # Cron job planifié
trigger.config.ts # Configuration Trigger.dev
.env.local # Variables d'environnement
Prochaines étapes
Maintenant que vous avez un système de tâches de fond fonctionnel, envisagez :
- Ajouter plus de workflows — traitement de commandes, génération de rapports, pipelines de données
- Implémenter l'idempotence — utilisez des clés uniques pour éviter les exécutions en double
- Configurer les alertes — notifications Slack ou email pour les tâches échouées
- Utiliser Trigger.dev avec une base de données — combinez avec Prisma ou Drizzle
- Explorer les patterns de fan-out — utilisez
batchTriggerAndWaitpour traiter de grands datasets - Auto-hébergement — Trigger.dev v3 peut être auto-hébergé si nécessaire
Conclusion
Trigger.dev v3 apporte le traitement des tâches de fond à l'écosystème TypeScript avec une expérience développeur qui semble native à Next.js. Au lieu de gérer des files Redis, des processus workers et de la logique de retry vous-même, vous écrivez de simples fonctions TypeScript et Trigger.dev gère l'infrastructure.
Dans ce tutoriel, vous avez construit un système complet d'automatisation d'onboarding avec exécution parallèle de tâches, workflows multi-étapes, cron jobs planifiés, gestion des erreurs avec retries, et déploiement en production. Les mêmes patterns s'appliquent à tout besoin de traitement de fond — de l'envoi d'emails au traitement de paiements en passant par l'exécution de pipelines IA.
Les points clés à retenir :
- Les tâches sont de simples fonctions TypeScript — pas de syntaxe spéciale à apprendre
triggerAndWaitpermet l'orchestration de workflows — composez des workflows complexes à partir de tâches simples- Les retries et la gestion des erreurs sont intégrés — configurez une fois, gérez les échecs avec élégance
- Les tâches planifiées remplacent les serveurs cron — pas d'infrastructure à gérer
- Le dashboard offre une observabilité complète — déboguez les problèmes en production avec logs, traces et métadonnées
Discutez de votre projet avec nous
Nous sommes ici pour vous aider avec vos besoins en développement Web. Planifiez un appel pour discuter de votre projet et comment nous pouvons vous aider.
Trouvons les meilleures solutions pour vos besoins.
Articles connexes

Upstash Redis et Next.js : Rate Limiting, Caching et Files de Messages
Apprenez à intégrer Upstash Redis dans une application Next.js pour implémenter le rate limiting, le caching côté serveur et les files de messages. Ce tutoriel couvre la configuration, les patterns de production et le déploiement serverless.

Construire un Agent IA Autonome avec Agentic RAG et Next.js
Apprenez a construire un agent IA qui decide de maniere autonome quand et comment recuperer des informations depuis des bases de donnees vectorielles. Un guide pratique complet avec Vercel AI SDK et Next.js, accompagne d'exemples executables.

Better Auth avec Next.js 15 : Le Guide Complet d'Authentification pour 2026
Apprenez à implémenter une authentification complète dans Next.js 15 avec Better Auth. Ce tutoriel couvre email/mot de passe, OAuth, sessions, protection des routes et contrôle d'accès basé sur les rôles.