--- title: after description: API Reference for the after function. --- `after` allows you to schedule work to be executed after a response (or prerender) is finished. This is useful for tasks and other side effects that should not block the response, such as logging and analytics. It can be used in [Server Components](/docs/app/getting-started/server-and-client-components) (including [`generateMetadata`](/docs/app/api-reference/functions/generate-metadata)), [Server Functions](/docs/app/getting-started/mutating-data), [Route Handlers](/docs/app/api-reference/file-conventions/route), and [Proxy](/docs/app/api-reference/file-conventions/proxy). The function accepts a callback that will be executed after the response (or prerender) is finished: ```tsx filename="app/layout.tsx" switcher import { after } from 'next/server' // Custom logging function import { log } from '@/app/utils' export default function Layout({ children }: { children: React.ReactNode }) { after(() => { // Execute after the layout is rendered and sent to the user log() }) return <>{children}> } ``` ```jsx filename="app/layout.jsx" switcher import { after } from 'next/server' // Custom logging function import { log } from '@/app/utils' export default function Layout({ children }) { after(() => { // Execute after the layout is rendered and sent to the user log() }) return <>{children}> } ``` > **Good to know:** `after` is not a [Request-time API](/docs/app/glossary#request-time-apis) and calling it does not cause a route to become dynamic. If it's used within a static page, the callback will execute at build time, or whenever a page is revalidated. ## Reference ### Parameters - A callback function which will be executed after the response (or prerender) is finished. ### Duration `after` will run for the platform's default or configured max duration of your route. If your platform supports it, you can configure the timeout limit using the [`maxDuration`](/docs/app/api-reference/file-conventions/route-segment-config/maxDuration) route segment config. ## Good to know - `after` will be executed even if the response didn't complete successfully. Including when an error is thrown or when `notFound` or `redirect` is called. - You can use React `cache` to deduplicate functions called inside `after`. - `after` can be nested inside other `after` calls, for example, you can create utility functions that wrap `after` calls to add additional functionality. ## Examples ### With request APIs Whether you can use request APIs like [`cookies`](/docs/app/api-reference/functions/cookies) and [`headers`](/docs/app/api-reference/functions/headers) inside `after` depends on where `after` is called from. #### In Route Handlers and Server Functions You can call `cookies` and `headers` directly inside the `after` callback when used in [Route Handlers](/docs/app/api-reference/file-conventions/route) and [Server Functions](/docs/app/getting-started/mutating-data). This is useful for logging activity after a mutation or API request. For example: ```ts filename="app/api/route.ts" highlight={2,10-16} switcher import { after } from 'next/server' import { cookies, headers } from 'next/headers' import { logUserAction } from '@/app/utils' export async function POST(request: Request) { // Perform mutation // ... // Log user activity for analytics after(async () => { const userAgent = (await headers()).get('user-agent') || 'unknown' const sessionCookie = (await cookies()).get('session-id')?.value || 'anonymous' logUserAction({ sessionCookie, userAgent }) }) return new Response(JSON.stringify({ status: 'success' }), { status: 200, headers: { 'Content-Type': 'application/json' }, }) } ``` ```js filename="app/api/route.js" highlight={2,10-16} switcher import { after } from 'next/server' import { cookies, headers } from 'next/headers' import { logUserAction } from '@/app/utils' export async function POST(request) { // Perform mutation // ... // Log user activity for analytics after(async () => { const userAgent = (await headers()).get('user-agent') || 'unknown' const sessionCookie = (await cookies()).get('session-id')?.value || 'anonymous' logUserAction({ sessionCookie, userAgent }) }) return new Response(JSON.stringify({ status: 'success' }), { status: 200, headers: { 'Content-Type': 'application/json' }, }) } ``` #### In Server Components (pages and layouts) [Server Components](/docs/app/getting-started/server-and-client-components) (including pages, layouts, and `generateMetadata`) **cannot** use `cookies`, `headers`, or other Request-time APIs inside `after`. This is because Next.js needs to know which part of the component tree accesses request data to support [Partial Prerendering](/docs/app/glossary#partial-prerendering-ppr) and [Cache Components](/docs/app/getting-started/caching), but `after` runs after React's rendering lifecycle. If you need request data inside an `after` callback in a Server Component, read it beforehand and pass the values in: ```tsx filename="app/page.tsx" highlight={8-10,12} switcher import { after } from 'next/server' import { cookies, headers } from 'next/headers' import { logUserAction } from '@/app/utils' export default async function Page() { // Read request data before `after` — this is allowed // These calls will be read during the component's rendering lifecycle const userAgent = (await headers()).get('user-agent') || 'unknown' const sessionCookie = (await cookies()).get('session-id')?.value || 'anonymous' after(() => { // Use the values read above logUserAction({ sessionCookie, userAgent }) }) return
Your session: {sessionCookie}
} ``` ```jsx filename="app/page.jsx" highlight={18-19,22-24} switcher import { Suspense } from 'react' import { after } from 'next/server' import { cookies } from 'next/headers' import { logUserAction } from '@/app/utils' export default function Page() { return ( <>Your session: {sessionCookie}
} ``` In this example, `