Skip to the solution
MediumFrontend8 min read

What is after() in Next.js and when should you use it?

60 views

The problem

Question presented to candidate: "After a user submits an order we write an audit log and send an analytics event, and both slow the response down. What does after() in Next.js do, and is it the right tool here?"

What a strong answer should cover:

  • after(callback) from next/server schedules work to run after the response (or prerender) has finished, so logging and analytics do not delay the user.
  • Where it works: Server Components (including generateMetadata), Server Actions, Route Handlers and Proxy; it is not a request-time API and does not make a route dynamic.
  • Request data: in Route Handlers and Server Actions you can call cookies()/headers() inside the callback; in Server Components you must read them before and close over the values.
  • It runs even when the response fails, calls notFound() or redirect(); in a static page it runs at build time or on revalidation.
  • Limits: the callback lives within the route's max duration; on serverless it relies on a waitUntil primitive; it is not a durable job queue, so critical work needs a real queue.

Clarifying questions expected:

  • "Must the audit log never be lost?" β€” if yes, write it in the request or enqueue it durably; after is best effort.
  • "Where is this deployed?" β€” a Node server, Vercel and adapters support it differently; static export does not.

Code / implementation expected: Yes β€” a Route Handler or Server Action that returns immediately and logs inside after().

  • nextjs
  • after
  • server
  • performance

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 8 sections

Read the code

Route Handler: respond now, log afterwards
// app/after/api/route.ts
import { after } from "next/server";
import { headers } from "next/headers";
import { log, sleep } from "@/lib/log";

export async function POST() {
  log("route", "mutation done, scheduling after()");
  after(async () => {
    const ua = (await headers()).get("user-agent"); // allowed inside after() in a Route Handler
    log("route", `after() started, user-agent=${ua}`);
    await sleep(1500); // pretend this is a slow analytics call
    log("route", "after() finished");
  });
  log("route", "returning response");
  return Response.json({ ok: true });
}
Server Component: read request data before after()
// app/after/dynamic/page.tsx
import { after } from "next/server";
import { cookies } from "next/headers";
import { log, sleep } from "@/lib/log";

export default async function Page() {
  const visitor = (await cookies()).get("visitor")?.value ?? "anonymous"; // read BEFORE after()
  after(async () => {
    await sleep(1000);
    log("page", `after() logged a view for ${visitor}`);
  });
  log("page", "render finished");
  return <h1>Hello {visitor}</h1>;
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 97 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextHard

How do you migrate from the Pages Router to the App Router in Next.js?

Continue