⚠️ Attention aux actions longues dans vos routes Next.js
Mike Codeur
Quand tu crées une route avec Next.js 15 via app/route.tsx
, il est tentant d’ajouter du traitement métier (tracking, logs, analytics, etc.) juste avant de faire un return
. Exemple classique :
export async function GET() {
await trackClick()
return NextResponse.redirect('https://autre-site.com')
}
Mais ce pattern peut vite poser problème…
😬 Le souci : tu bloques la réponse HTTP
Dans ce cas-là, l’utilisateur attend la fin du trackClick()
avant d’être redirigé. Et si ce traitement prend 200ms ou plus, tu viens de retarder la réponse HTTP pour rien.
Pire encore :
🧨 Si tu veux "optimiser" en évitant await
:
void trackClick()
return NextResponse.redirect('https://autre-site.com')
➡️ Tu penses avoir gagné du temps… mais le process peut se faire tuer juste après le return
(notamment sur Vercel en edge/serverless). Résultat ?
Ton code trackClick()
peut ne jamais s’exécuter ou s’exécuter aléatoirement.
✅ La bonne pratique : after()
ou waitUntil()
🧠 Si tu es dans une App Route Next.js 15.1+ :
import { after } from 'next/server'
export async function GET() {
after(async () => {
try {
await trackClick()
} catch (e) {
console.error('Tracking échoué', e)
}
})
return NextResponse.redirect('https://autre-site.com')
}
✅ Le code sera exécuté après que la réponse ait été envoyée (ou après le prerender), sans bloquer l’utilisateur, et sans risque d’annulation prématurée. C’est prévu pour du logging, du tracking, ou d'autres effets secondaires non-critiques pour la réponse.
💡 Et si tu es dans une Vercel Function classique :
import { waitUntil } from '@vercel/functions'
async function trackClick() {
// Exemple de tracking
const res = await fetch('https://my-analytics-service.com/track')
return res.json()
}
export function GET(request: Request) {
waitUntil(trackClick().then((json) => console.log('Track response', json)))
return new Response('Redirection terminée')
}
✅ waitUntil()
permet de lancer une tâche en arrière-plan dans l’environnement Vercel Function sans bloquer la réponse principale.
🧪 Exemple réel mesuré :
J’ai loggué l’exécution avec console.time()
sur Vercel. Résultat :
- Avec le
await
dans la route : 400+ ms - Avec
after()
ouwaitUntil()
, la réponse HTTP part en <300ms, et le tracking se fait après, sans perte
🚀 TL;DR :
- Ne mets jamais un traitement long (BDD, logs, analytics) avant ton
return
si tu veux une UX rapide void
sansawait
≠ safe en edge/serverless- Utilise
after()
(Next.js 15.1+) ouwaitUntil()
(Vercel Functions) pour garantir que ton code s’exécute sans bloquer la réponse et sans être annulé prématurément
C’est un petit détail… mais c’est ce genre de détails qui font la diff quand tu codes des outils à fort trafic ⚡️