Skip to main content

Server No Shared Module State

Source: .agents/references/coding-standard/vercel-react-best-practices/rules/server-no-shared-module-state.md

Metadata

  • title: Avoid Shared Module State for Request Data
  • impact: HIGH
  • impactDescription: prevents concurrency bugs and request data leaks
  • tags: server, pages-router, ssr, gssp, concurrency, security, state

Content

This repo: Pages Router only — applies to getServerSideProps, SSR, and concurrent page renders. Module scope is not request-local.

Avoid Shared Module State for Request Data

During getServerSideProps and SSR, avoid mutable module-level variables for request-scoped data. Server renders can run concurrently in the same process. If one request writes shared module state and another reads it, you can get race conditions, cross-request contamination, and security bugs.

Treat module scope on the server as process-wide shared memory, not request-local state.

Incorrect (request data leaks across concurrent renders):

let currentUser: User | null = null

export const getServerSideProps: GetServerSideProps = async () => {
currentUser = await auth()
return { props: { userName: currentUser?.name ?? null } }
}

If two requests overlap, request A can set currentUser, then request B overwrites it before A's props are returned.

Correct (keep request data in the data function closure / return value):

export const getServerSideProps: GetServerSideProps = async () => {
const user = await auth()
return { props: { userName: user?.name ?? null } }
}

Safe exceptions:

  • Immutable static assets or config loaded once at module scope
  • Shared caches intentionally designed for cross-request reuse and keyed correctly
  • Process-wide singletons that do not store request- or user-specific mutable data

For static assets and config, see Hoist Static I/O to Module Level.