Retour aux articles
Thursday, April 17, 2025132 vues6

⚠️ 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:

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:

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+):

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 ⚡️

Rejoins The Agentic Dev

Chaque semaine : outils, workflows et stratégies pour coder avec les agents IA comme un pro.

Workflows agentic testés en prod
Outils IA qui marchent vraiment
+35 000 développeurs déjà inscrits

Gratuit · 1 email / semaine · +1250€ de formations offertes