Retour aux articles
Thursday, April 17, 202513 vues1

⚠️ Be Careful with Long-Running Actions in Next.js Route Handlers (`route.tsx`)

Mike Codeur

Next
React
JavaScript

⚠️ Be Careful with Long-Running Actions in Next.js Route Handlers (route.tsx)

When you're building a route in Next.js 14/15 using app/route.tsx, it's tempting to include business logic (tracking, logging, analytics, etc.) right before returning a response. A common example:

TYPESCRIPT
export async function GET() {
  await trackClick()
  return NextResponse.redirect('https://other-site.com')
}

But this pattern can quickly become a problem…


😬 The Problem: You're Blocking the HTTP Response

In this case, the user has to wait for trackClick() to complete before being redirected. If this takes 200ms or more, you're delaying the response for no reason.

Worse:

🧨 If You Try to "Optimize" by Removing await:

TYPESCRIPT
void trackClick()
return NextResponse.redirect('https://other-site.com')

➡️ It might look like you've improved performance, but the process may be killed right after return (especially on Vercel edge/serverless). The result?

Your trackClick() might never run or run inconsistently.


✅ The Right Way: after() or waitUntil()

🧠 In an App Route (Next.js 15.1+):

TYPESCRIPT
import { after } from 'next/server'

export async function GET() {
  after(async () => {
    try {
      await trackClick()
    } catch (e) {
      console.error('Tracking failed', e)
    }
  })

  return NextResponse.redirect('https://other-site.com')
}

✅ The code inside after() will run after the response is sent (or after prerendering). It won’t block the user and won’t be cut off unexpectedly. It’s perfect for logging, tracking, or other side effects that don’t affect the main response.

💡 In a Vercel Function:

typescript

PLAINTEXT
import { waitUntil } from '@vercel/functions'

async function trackClick() {
  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('Redirect complete')
}

waitUntil() lets you execute background tasks after the response is sent, safely and without blocking.


🧪 Real-World Example:

Using console.time() on Vercel, I measured:

  • With await inside the route: 400+ ms execution
  • With after() or waitUntil(): response sent in <300ms, tracking continues safely afterward

🚀 TL;DR:

  • Never put long operations (DB writes, logs, analytics) before your return if you want fast responses
  • void without await ≠ safe in edge/serverless environments
  • Use after() (Next.js 15.1+) or waitUntil() (Vercel Functions) to ensure background code runs without blocking the user or being killed early

It’s a small detail—but this kind of detail makes all the difference when you're building fast, reliable tools ⚡️

Abonnes-toi à la NewsLetter

Apprends les meilleures pratiques pour devenir un développeur web moderne (JavaScript / React / Next).

Gagner sa vie grâce au code
Devenir développeur Freelance
+35 000 développeurs déjà inscrits.

Accès instantané. Aucune carte de crédit requise.

Rejoins +35 000 développeurs déjà inscrits.