Running a background job after an API response

Hi!

In my nextjs application (pages router + trpc), I have an API call named createPlaytest as part of a simple CRUD. Right now, when it finishes creating a database entry, two things happen:

  1. I call sendNotifications, an async function, without awaiting it. This sends discord notifications to other users that a new playtest has been created so they can check it out. It executes in less than 3 seconds when ran manually in prod.
  2. I return the id of the database entry that was just created as the query response, so the front-end can redirect the user to the /playtest/{id} page.

The idea is to make the user experience better, by not having the user wait for a slow operation to finish before they get to see the result. The job is executed in the background while the user gets a response almost immediately.

const createPlaytest =  protectedProcedure
    .input(CreatablePlaytestSchema)
    .mutation(async ({ input, ctx: { auth: { userId }} }) => {
        // Check permissions
        const { permissions, user } = await getPermissions(userId)
        if (!user || !permissions.canCreate) throw new Error('Unauthorized')
        
        // Create playtest
        const playtests = await Collections.playtests()
        const newPlaytest: Omit<Playtest, '_id'> = {
            ...input,
            userId,
            createdTimestamp: Date.now(),
            closedManually: false,
            applications: [],
        }
        const result = await playtests.insertOne(newPlaytest)
        if (!result.acknowledged) throw new Error('Internal server error')

        // Not awaited - this shouldn't block the user's UI.
        playtestCreatedNotification({...newPlaytest, _id: result.insertedId.toString() }, user)

        return result.insertedId.toString()
    })

The project is open source, so if you’d like to see more detail, you can find the source code here: questcheck/src/server/routers/playtests.ts at main · Trekiros/questcheck · GitHub

What I expected to happen: the job would run in the background after the response was sent, as long as it would fit within the 10 seconds a Vercel process is allowed to stay alive

What happened instead: this works fine in dev, but in prod on Vercel, the moment the response is sent, the process is killed and the job is never completed

So, is there a way I can keep the process alive after the response has been sent? Or do I need a completely different approach? What are my options here?
Thank you

Deployment URL or Custom Domain: https://www.questcheck.org
Environment (local, preview, production): prod
Project Framework: nextjs
Build Settings:
  Framework Preset: nextjs
  Build Command (if not default): default
  Output Directory (if not default): default
  Install Command (if not default): default
Node/Runtime Version: 20.X
Package Manager: npm
Relevant Packages: trpc

(also of note, this project is at hobby level, so I can’t toggle on serverless servers, which… I believe might solve this issue?)

Hi, @trekiros!

Appreciate your patience :pray:

Did you manage a workaround?

Hi!

I didn’t manage to find a good solution - right now I just await the “background” job. It makes the user experience worse, though, so I’m not a huge fan of this solution.

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