Fire-and-forget a HTTP request

Let’s say I have an expensive side-effect that takes 30s to run, I’d like to invoke on a handler. I know I don’t want to block the user-path though, so I’ve put this in an external API.

However, this HTTP endpoint is still designed to return a status code after it succeeds. How do I make sure I successfully send a request, but don’t block on its completion?

Example approach 1:

await fetch(expensiveFunction)
return NextResponse.json(200)

This is bad, since it blocks the response to the user for 30s.

Example approach 2:

fetch(expensiveFunction)
return NextResponse.json(200)

This fails, since as soon as we respond to the user, we don’t run this expensive background function. We usually don’t even get to submit our HTTP request.

The ideal approach combines both:

Example approach 3:

await fetchButWaitUntilSubmitOnly(expensiveFunction)
return NextResponse.json(200)

This would be awesome, ie: wait until the HTTP request is successfully submitted, but do not wait until the endpoint responds.

Is there any way to do this in a Vercel API endpoint? Or any other ways to solve this problem of running an expensive side effect?

Hi, you can use the waitUntil function from the @vercel/functions package for this exact use case. In your example, it would look like:

import { waitUntil } from '@vercel/functions'

async function expensiveFunction() {}

export function GET(request: Request) {
  waitUntil(expensiveFunction);
 
  return NextResponse.json(200)
}

Check out the documentation for more details here: Functions API Reference

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.