Serverless App Services and deployments
Runtime and caching
How requests reach your deployment, what your server code runs with, and how caching works.
How requests are routed
Every deployment hostname and custom domain is served by the platform's edge (CloudFront). For each request, the edge looks up which deployment the hostname belongs to and sends the request to its static files or its server function:
| Request path | Served from |
|---|---|
/_next/static/… | Static files |
Ends in a file extension (/logo.svg, /robots.txt), outside /api/ | Static files |
| Anything else | The server function (Next.js) |
For Node.js server Serverless App Services every request goes to the server, files included.
For static Serverless App Services, a path without a file extension is served from <path>/index.html, so /about serves /about/index.html and / serves /index.html.
A Next.js route whose path ends in an extension, such as a generated /sitemap.xml or /feed.rss, is looked up as a static file and never reaches the server function. Generate those files at build time into public/, or serve them under /api/.
Your app sees the hostname the visitor used in the x-forwarded-host header; the Host header is the function's own.
Server functions
Next.js deployments run in one AWS Lambda function per deployment:
| Runtime | Node.js 22 on arm64 |
| Memory | 1,024 MB, or 128–10,240 MB set in the Serverless App Service's Settings → Functions (CPU scales with memory) |
| Timeout | 30 seconds per request, or 1–60 seconds set in Settings → Functions |
| Region | Resolved from the Serverless App Service's location when the deployment is published |
| Environment | The Serverless App Service's variables for the deployment's target, the platform variables, and NODE_ENV=production |
Responses are buffered: a streamed response (React streaming, server-sent events) reaches the visitor in one piece when the function finishes. AWS limits buffered responses to 6 MB.
Permissions
Each organization has one runtime role, shared by its deployments. It allows writing logs and reading and writing the organization's own databases and buckets (all of them, not only the linked ones) and the organization's part of the Next.js cache. It allows nothing else in AWS, and nothing that belongs to another organization. The AWS SDK picks up the role's credentials automatically.
Function URLs are public
The edge calls the function through a public function URL, as the platform's own apps do. That URL can also be called directly, bypassing the edge, so authenticate your sensitive endpoints in your app rather than relying on the edge.
To close that path, turn on Only accept requests through the edge in Settings → Deployment Protection. Deployments published afterwards get a secret of their own, which the edge adds to every request it sends to the function as the x-si-origin header (a visitor can't set it). Next.js functions refuse requests without it with 403. Node.js servers get it as SI_ORIGIN_SECRET and should compare the header with it themselves (in constant time) before answering. Deployments published before the change keep working as they were; redeploy to apply it.
Caching
The edge caches a response only when its Cache-Control allows it; without that header nothing is cached.
- The cache key is the hostname, path and full query string.
- Cookies aren't part of the cache key, but your function receives them. A response that depends on cookies must be
privateorno-store, or one visitor's response can be served to another. - The edge compresses responses with gzip or Brotli.
- Uploaded static files:
/_next/static/files are cached for a year (immutable); every other file is revalidated on each request (max-age=0, must-revalidate).
Next.js incremental cache
Prerendered pages and fetch cache entries are stored per deployment, so a new deployment starts from its own build's pages. The platform sets CACHE_BUCKET_NAME, CACHE_BUCKET_KEY_PREFIX, CACHE_BUCKET_REGION and CACHE_DYNAMO_TABLE on the function for this, replacing Serverless App Service variables with the same names.
Time-based revalidation (revalidate) works: a stale page is served once and regenerated by the same function. On-demand revalidation (revalidateTag, revalidatePath) works too: revalidated tags are recorded in a table the platform keeps for your organization, and the next read of anything they cover regenerates it. The edge doesn't hear about revalidations, so a response it has cached stays until its Cache-Control lets it expire: for pages that must change the moment you revalidate, keep s-maxage short. A Serverless App Service with its own open-next.config.ts builds with that instead of the platform's.