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.