From a0daf0adaf7cb58bbabe274267ccf93132ab2bfb Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:23:26 +0100 Subject: [PATCH 01/23] docs(aws): document the aws-apigw-streaming and aws-lambda-compressed wrappers - Add the aws-apigw-streaming wrapper (4.1.0) - Add the aws-lambda-compressed wrapper (3.5.6) - aws-lambda-streaming now provides waitUntil (4.1.6) - Document BROTLI_QUALITY --- pages/aws/config/overrides/wrapper.mdx | 40 ++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/pages/aws/config/overrides/wrapper.mdx b/pages/aws/config/overrides/wrapper.mdx index 1728b3c1..85e90580 100644 --- a/pages/aws/config/overrides/wrapper.mdx +++ b/pages/aws/config/overrides/wrapper.mdx @@ -7,7 +7,7 @@ Couple of things to note : - If you want to use streaming (for the `node` runtime of next), you'll need to create a `StreamCreator` and pass it to the `handler`. You can find some example in the [node](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/wrappers/node.ts) or [aws-lambda-streaming](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/wrappers/aws-lambda-streaming.ts) wrapper. - If you don't use streaming (like in the default `aws-lambda` wrapper), you may still need to provide a fake `StreamCreator` to the `handler` to avoid a weird issue with Node itself (see [here](https://github.com/opennextjs/opennextjs-aws/blob/f685ddea8f8a5c82591dc02713aff7138f2d9896/packages/open-next/src/overrides/wrappers/aws-lambda.ts#L49-L65) for an example and a more thorough explanation). - If you use the `edge` runtime of Next (either for the external middleware or for an `edge` route or page), you don't need the `StreamCreator` at all. -- If you are in a serverless environment and it supports `waitUntil`, you should pass it to the handler as it is done in the [cloudflare-edge wrapper](https://github.com/opennextjs/opennextjs-aws/blob/87b59e59a8a0bf1e83d2d1df9efa0ad3bfc912f5/packages/open-next/src/overrides/wrappers/cloudflare-edge.ts#L65-L67). This might not be necessary depending on where you run it (for example the `aws-lambda-streaming` or the `node` wrapper doesn't need it.) +- If you are in a serverless environment and it supports `waitUntil`, you should pass it to the handler as it is done in the [cloudflare-edge wrapper](https://github.com/opennextjs/opennextjs-aws/blob/87b59e59a8a0bf1e83d2d1df9efa0ad3bfc912f5/packages/open-next/src/overrides/wrappers/cloudflare-edge.ts#L65-L67). The `aws-lambda-streaming` and `aws-apigw-streaming` wrappers provide their own `waitUntil` (pending promises are awaited before the response stream is closed). This might not be necessary depending on where you run it (for example the `node` wrapper doesn't need it as it is a long running server.) ## Included Wrappers @@ -22,12 +22,48 @@ The `aws-lambda` Wrapper is the default wrapper for AWS Lambda. It is used by de ### aws-lambda-streaming -The `aws-lambda-streaming` Wrapper is a wrapper that allows you to use streaming in AWS Lambda. Streaming must be enabled for this lambda. +The `aws-lambda-streaming` Wrapper is a wrapper that allows you to use streaming in AWS Lambda. Streaming must be enabled for this lambda and it must be invoked through a Lambda Function URL. + +The response is compressed (`br`, `gzip` or `deflate`) according to the `Accept-Encoding` header of the request. + +#### Features + +- [x] Streaming +- [x] Proper support for `waitUntil` (available since `@opennextjs/aws` 4.1.6) +- [x] Compression + +### aws-apigw-streaming + +Available since `@opennextjs/aws` 4.1.0 + +The `aws-apigw-streaming` Wrapper allows you to use streaming when the server function is behind an [API Gateway REST API with response streaming](https://aws.amazon.com/about-aws/whats-new/2025/11/api-gateway-response-streaming-rest-apis/) (`ResponseTransferMode: STREAM`) instead of a Lambda Function URL. + +It should be used with the `aws-apigw-v1` (REST API) or `aws-apigw-v2` (HTTP API) converter. + +Unlike `aws-lambda-streaming`, it never compresses the response because API Gateway streaming does not support content encoding. Compression should be handled by the CDN in front of API Gateway (e.g. CloudFront). #### Features - [x] Streaming - [x] Proper support for `waitUntil` +- [ ] Compression + +### aws-lambda-compressed + +Available since `@opennextjs/aws` 3.5.6 + +The `aws-lambda-compressed` Wrapper is the same as the `aws-lambda` Wrapper but it also compresses the response (`br`, `gzip` or `deflate`) according to the `Accept-Encoding` header of the request. +It can be useful to reduce the size of the response as AWS Lambda has a limit of 6MB for the response payload. + +#### Features + +- [ ] Streaming +- [ ] Proper support for `waitUntil` +- [x] Compression + +### Compression + +The Brotli compression quality used by the `aws-lambda-streaming` and `aws-lambda-compressed` wrappers can be set with the `BROTLI_QUALITY` environment variable (from `0` to `11`). It defaults to `6`. ### cloudflare-edge From 3598469acb4ac9df1e9d152046cd5b9bdb82b6d9 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:23:38 +0100 Subject: [PATCH 02/23] docs(aws): update the list of wrappers in the components overview --- pages/aws/inner_workings/components/overview.mdx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pages/aws/inner_workings/components/overview.mdx b/pages/aws/inner_workings/components/overview.mdx index d415d6f0..d23d8d49 100644 --- a/pages/aws/inner_workings/components/overview.mdx +++ b/pages/aws/inner_workings/components/overview.mdx @@ -63,9 +63,16 @@ The `handler` is the original handler that is being wrapped. The `converter` is Here is a list of the provided wrappers: - `aws-lambda` - The default AWS Lambda wrapper - It is the default wrapper -- `aws-lambda-streaming` - The AWS Lambda wrapper with streaming support +- `aws-lambda-compressed` - The AWS Lambda wrapper with compression support +- `aws-lambda-streaming` - The AWS Lambda wrapper with streaming support (Lambda Function URL) +- `aws-apigw-streaming` - The AWS Lambda wrapper with streaming support behind an API Gateway - `node` - The Node wrapper - Create a node server, not suitable for serverless -- `cloudflare` - The Cloudflare wrapper - For Cloudflare Worker +- `cloudflare-edge` - The Cloudflare wrapper for the edge runtime - For Cloudflare Workers +- `cloudflare-node` - The Cloudflare wrapper for the node runtime - Used by `@opennextjs/cloudflare` +- `express-dev` - The Express wrapper - For development only +- `dummy` - The Dummy wrapper - Forwards the event to the handler + +See the [wrapper override](/aws/config/overrides/wrapper) page for more details. ##### Aws Lambda streaming From 755fd0cd0576f299d5a3b53644bf534813a5497f Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:24:19 +0100 Subject: [PATCH 03/23] docs(aws): update the lists of included wrappers, tag caches and queues --- pages/aws/config/custom_overrides.mdx | 2 +- pages/aws/config/reference.mdx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pages/aws/config/custom_overrides.mdx b/pages/aws/config/custom_overrides.mdx index c9b29ca9..c7c3670d 100644 --- a/pages/aws/config/custom_overrides.mdx +++ b/pages/aws/config/custom_overrides.mdx @@ -312,7 +312,7 @@ const config = { export default config; ``` -[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache) ones are `'dynamodb' | 'dynamodb-lite' | 'fs-dev' | 'dummy'` +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache) ones are `'dynamodb' | 'dynamodb-lite' | 'dynamodb-nextMode' | 'fs-dev' | 'fs-dev-nextMode' | 'dummy'` ## Custom Origin Resolver diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx index cad02f40..f77b39e5 100644 --- a/pages/aws/config/reference.mdx +++ b/pages/aws/config/reference.mdx @@ -40,7 +40,7 @@ Each server config will be under it's own key in the config object. Here are all This is the entrypoint of the server. Be aware that it might not be enough to change this to make it work on said platform. This is only the entrypoint, you might need to change other parts of the server to make it work on the platform. - Possible values are: `aws-lambda`, `aws-lambda-streaming`, `cloudflare-edge`, `cloudflare-node`, `node`, `express-dev`, `dummy` or a `LazyLoadedOverride` that will return the wrapper. + Possible values are: `aws-lambda`, `aws-lambda-compressed`, `aws-lambda-streaming`, `aws-apigw-streaming`, `cloudflare-edge`, `cloudflare-node`, `node`, `express-dev`, `dummy` or a `LazyLoadedOverride` that will return the wrapper. #### [`converter`](overrides/converter) @@ -135,13 +135,13 @@ Each server config will be under it's own key in the config object. Here are all Add possibility to override the default tag cache. Used for revalidateTags and revalidatePath. - Possible values are: `dynamodb`, `dynamodb-lite`, `fs-dev`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. + Possible values are: `dynamodb`, `dynamodb-lite`, `dynamodb-nextMode`, `fs-dev`, `fs-dev-nextMode`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. #### [`queue`](overrides/queue) Add possibility to override the default queue. Used for ISR revalidation requests. - Possible values are: `sqs`, `sqs-lite`, `dummy` or a `LazyLoadedOverride` that will return the queue. + Possible values are: `sqs`, `sqs-lite`, `direct`, `dummy` or a `LazyLoadedOverride` that will return the queue. #### [`proxyExternalRequest`](overrides/proxy_external_request) @@ -239,6 +239,8 @@ Each server config will be under it's own key in the config object. Here are all Possible values are: `dynamodb`, `dynamodb-lite`, `fs-dev`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. + Tag caches in `nextMode` (i.e. `dynamodb-nextMode`) do not need to be initialized. + From 71fb3a2d5d8fa0c7ad6069c8006cf20fce77d389 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:24:34 +0100 Subject: [PATCH 04/23] docs(aws): update the install options - arch is passed as --cpu and has no default - document os - nodeVersion is deprecated (4.1.14) --- pages/aws/config/reference.mdx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx index f77b39e5..418edfb8 100644 --- a/pages/aws/config/reference.mdx +++ b/pages/aws/config/reference.mdx @@ -61,17 +61,22 @@ Each server config will be under it's own key in the config object. Here are all ##### `arch` - This is the architecture of the server. It is a string and by default, it is set to `x64`. + This is the architecture of the server. It is passed to npm as `--cpu` to select the platform specific optional dependencies (i.e. sharp's `@img/*` packages). + It is not set by default. Note that when `install` is not set for the image optimization server, sharp is installed for `arm64`, `linux` and `glibc`. Possible values are: `x64`, `arm64` - ##### `nodeVersion` + ##### `os` - This option will be passed to the postinstall script of sharp. It is used by `node-gyp`. + The operating system of the server. It is passed to npm as `--os`. By default, it is set to `linux`. + + ##### `nodeVersion` - Deprecated + + This option is ignored since `@opennextjs/aws` 4.1.14 because npm no longer supports the `--target` flag. ##### `libc` - Override libc of native modules to install. + Override libc of native modules to install. It is passed to npm as `--libc`. Possible values are: `glibc`, `musl` From d5201f1b93b1281b885f8297ce8016a15a125449 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:25:05 +0100 Subject: [PATCH 05/23] docs(aws): document routePreloadingBehavior --- pages/aws/config/reference.mdx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx index 418edfb8..afccf7c7 100644 --- a/pages/aws/config/reference.mdx +++ b/pages/aws/config/reference.mdx @@ -126,6 +126,18 @@ Each server config will be under it's own key in the config object. Here are all This option is deprecated and doesn't work for Next 14.2+. + ### `routePreloadingBehavior` + + Next.js loads the code of a route the first time it is requested. This option allows to preload all the routes of the server ahead of time to reduce the latency of the first requests. + You should do your own testing to choose the one that suits you best. Route preloading requires Next.js 15+. + + Possible values are: + + - `none` - No preloading of the routes. This is the default. + - `withWaitUntil` - Preload the routes in the background of the first request using the `waitUntil` provided by the wrapper. It falls back to `none` when the wrapper doesn't provide a `waitUntil` (i.e. the `aws-lambda-streaming`, `aws-apigw-streaming` and Cloudflare wrappers provide one). + - `onWarmerEvent` - Preload the routes on the warmer event. It must be implemented by the wrapper, it is only supported by the `aws-lambda-streaming` and `aws-apigw-streaming` wrappers. + - `onStart` - Preload the routes before the handler is created. This is a blocking operation that may increase the cold start time a lot. It is useful for long running servers or in serverless with careful testing. + ### `override` For both default and splitted server, in addition to `override` in the common options, you can also use the following options: From dcea1a1e1ec5c9be6d09bf1de1f1acaac190ec1d Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:25:33 +0100 Subject: [PATCH 06/23] docs(aws): document dangerous.middlewareHeadersOverrideNextConfigHeaders --- pages/aws/config/reference.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx index afccf7c7..e8d90a3e 100644 --- a/pages/aws/config/reference.mdx +++ b/pages/aws/config/reference.mdx @@ -337,5 +337,13 @@ headersAndCookiesPriority: (event) => { }, ``` +#### `middlewareHeadersOverrideNextConfigHeaders` + +Available since `@opennextjs/aws` 3.8.0 + +When set to `true`, the response headers set by the middleware take precedence over the headers set via the [`headers` option](https://nextjs.org/docs/app/api-reference/config/next-config-js/headers) of the Next config, in line with the [Next.js execution order](https://nextjs.org/docs/app/api-reference/file-conventions/middleware#execution-order). + +It's a boolean and by default, it is set to `false` (the headers from the Next config take precedence). + From e372c0ddefffb34033e777de8bd5ab3c1200d0a2 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:26:04 +0100 Subject: [PATCH 07/23] docs(aws): document the nextMode tag caches and stale-while-revalidate support - Document the original and nextMode modes - Document dynamodb-nextMode and fs-dev-nextMode - Document isStale and the writeTags signature change (3.10.0) --- pages/aws/config/overrides/tag_cache.mdx | 42 ++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/pages/aws/config/overrides/tag_cache.mdx b/pages/aws/config/overrides/tag_cache.mdx index a5f78e9f..23aabbcd 100644 --- a/pages/aws/config/overrides/tag_cache.mdx +++ b/pages/aws/config/overrides/tag_cache.mdx @@ -1,3 +1,5 @@ +import { Callout } from "nextra/components"; + This override is used by the [`cache` adapter](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/adapters/cache.ts) that is provided by OpenNext to the NextServer. It is also used by OpenNext if `enableCacheInterception` is set to `true` in the configuration and by the `initializationFunction` for prepopulating the cache. It is used for the cache tags (i.e. `revalidateTag` and `revalidatePath`). It does not handle anything related to the ISR/SSG cache or the fetch cache used by Next.js. @@ -7,9 +9,33 @@ The current implementation differs from the way Next.js standalone handle cache We choose to go another way. We store tags for every path that exists in the cache. This way, we can easily know if a path is stale by just checking the path instead of every tags used. This approach is more write heavy but it's a tradeoff we are willing to make. This also has the drawback of needing to prepopulate the cache with all the tags that are used in the application. This is done by the `initializationFunction`. -We might allow to choose how cache tags are handled in the future depending on the `TagCache` implementation. If you need this feature, feel free to open an issue on the [GitHub repository](https://github.com/opennextjs/opennextjs-aws). +## Modes + +A `TagCache` can work in one of two modes, set with its `mode` property: + +- `original` (default) - The approach described above. Tags are stored for every path, so a single lookup per path is needed on read. It needs to be prepopulated at build time and is write heavy. It allows the [automatic CDN invalidation](/aws/config/overrides/automatic_cdn_invalidation) to resolve the paths of a tag. +- `nextMode` - Similar to the way Next.js handles tags. Only the time at which a tag has been revalidated is stored, and every tag of an entry is checked on read. It doesn't need to be prepopulated and writes very little, but reads more. Path resolution for the automatic CDN invalidation is only available when the implementation provides the optional `getPathsByTags` method. + +## Custom implementations + +If you want to better understand how to implement your own TagCache, the easiest way would be to take a look at the existing [included TagCache](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache) and at the [types](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/types/overrides.ts). + +### Stale-while-revalidate + +Since `@opennextjs/aws` 3.10.0, `revalidateTag(tag, profile)` (Next.js 16+) can mark the entries as stale instead of expiring them right away. Stale entries are still served while they are revalidated in the background. + +To support it, a `TagCache` must store the optional `stale` and `expire` timestamps (in milliseconds since epoch) passed to `writeTags` and implement the optional `isStale` method: + +- `original` mode: `isStale(path: string, lastModified?: number): Promise` +- `nextMode`: `isStale(tags: string[], lastModified?: number): Promise` -If you want to better understand how to implement your own TagCache, the easiest way would be to take a look at the existing [included TagCache](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache). +Without `isStale`, stale entries are not detected, only expired ones are. + + + The signature of `writeTags` changed in `@opennextjs/aws` 3.10.0. It now receives `OriginalTagCacheWriteInput[]` + (`{ tag, path, revalidatedAt?, stale?, expire? }`) in the `original` mode and `NextModeTagCacheWriteInput[]` + (`string | { tag, stale?, expire? }`) in `nextMode`. Custom implementations must be updated. + ## Included TagCache @@ -35,7 +61,13 @@ This implementation is a lighter version of the `dynamodb` TagCache as it uses ` ### dynamodb-nextMode -TBA +The DynamoDBNextMode TagCache will store the time at which each tag has been revalidated in a DynamoDB table. It works in `nextMode` and uses `aws4fetch` to interact with DynamoDB. +It doesn't need to be prepopulated by the `initializationFunction`, and it doesn't support resolving the paths of a tag for the automatic CDN invalidation. + +##### Requirements + +- You need to provide the `CACHE_DYNAMO_TABLE`, `CACHE_BUCKET_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables to your server. +- DynamoDB table should have a primary key `path` of type `String` and a sort key `tag` of type `String`. (It can reuse the same table as the one used by the default `tagCache`) ### dummy @@ -44,3 +76,7 @@ The Dummy TagCache is a dummy implementation that will throw an exception. It sh ### fs-dev The FsDev TagCache is a simple implementation that stores the cache tags in a file in the `.open-next/cache` folder and interact with it using the filesystem. It is useful for development purposes only. + +### fs-dev-nextMode + +The FsDevNextMode TagCache is a simple implementation that works in `nextMode` and stores the cache tags in memory. It is useful for development purposes only. From f6379f70fbd71b0870000ed9f03b1a2090012db1 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:26:33 +0100 Subject: [PATCH 08/23] docs(aws): document native CDN tag invalidation (invalidateTags) --- .../overrides/automatic_cdn_invalidation.mdx | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pages/aws/config/overrides/automatic_cdn_invalidation.mdx b/pages/aws/config/overrides/automatic_cdn_invalidation.mdx index c9a9c098..49c2e4db 100644 --- a/pages/aws/config/overrides/automatic_cdn_invalidation.mdx +++ b/pages/aws/config/overrides/automatic_cdn_invalidation.mdx @@ -7,6 +7,34 @@ It will be called for `revalidatePath`, `revalidateTag` and `res.revalidate()`. If you want to better understand how to implement your own Automatic CDN Invalidation, the easiest way would be to take a look at the existing [included Automatic CDN Invalidation](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/cdnInvalidation) +## Custom implementations + +An Automatic CDN Invalidation override must implement `invalidatePaths` and can optionally implement `invalidateTags`: + +```ts +type CDNInvalidationHandler = { + name: string; + invalidatePaths: (paths: CDNPath[]) => Promise; + invalidateTags?: (tags: string[]) => Promise; +}; +``` + +### `invalidatePaths` + +Invalidates the CDN entries of the given paths. Each path includes the path before (`initialPath`) and after (`rawPath`) routing as well as the routes that matched while resolving the request (`resolvedRoutes`). + +For `revalidateTag` and `revalidatePath`, the paths are resolved from the tags by the [Tag Cache](/aws/config/overrides/tag_cache). Tag caches in `nextMode` can only resolve paths when they implement the optional `getPathsByTags` method. + +### `invalidateTags` + +Available since `@opennextjs/aws` 4.1.14 + +If your CDN supports invalidating its cache by tags, you can implement `invalidateTags` to invalidate the original cache tags directly instead of resolving them to paths. + +- It is called once per `revalidateTag` or `revalidatePath` call, after the tag cache has been updated, with the tags as passed to Next.js: hard tags from `revalidateTag()` and soft tags (prefixed with `_N_T_/`) from `revalidatePath()`. Tags are not expanded, i.e. the hard tags of the paths matching a soft tag are not added. +- When it is provided, `invalidatePaths` is no longer called for `revalidateTag` and `revalidatePath`. It is still called for `res.revalidate()` in the Pages Router. +- The CDN integration must associate cached entries with the same tags, both hard and soft, for the invalidation to have an effect. + ## Included Automatic CDN Invalidation ### dummy From 76c63d6f2e3afb15f4b60fc4792af98003e9222f Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:26:45 +0100 Subject: [PATCH 09/23] docs(aws): the sqs queues send messages in the background when waitUntil is available --- pages/aws/config/overrides/queue.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/aws/config/overrides/queue.mdx b/pages/aws/config/overrides/queue.mdx index c4d2961e..9f8a3ddf 100644 --- a/pages/aws/config/overrides/queue.mdx +++ b/pages/aws/config/overrides/queue.mdx @@ -17,6 +17,8 @@ Couple of things to note : The SQS Queue will send a message to an SQS queue for each route that needs to be revalidated. It is used by default if you don't provide any Queue in your configuration. It uses the `@aws-sdk/client-sqs` to interact with SQS. +Since `@opennextjs/aws` 4.1.6, the message is sent in the background when the wrapper provides a `waitUntil` (i.e. `aws-lambda-streaming` or `aws-apigw-streaming`) so that it does not delay the response. Otherwise, the response is sent once the message has been sent. The same applies to `sqs-lite`. + #### Requirements - You need to provide the `REVALIDATION_QUEUE_URL` environment variable to your server. From d5e831fe4fbe48c758f9d693ad78cd3f5d66cd1e Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:26:49 +0100 Subject: [PATCH 10/23] docs(aws): fix the heading of the node converter --- pages/aws/config/overrides/converter.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/aws/config/overrides/converter.mdx b/pages/aws/config/overrides/converter.mdx index b23346d1..cfa722e4 100644 --- a/pages/aws/config/overrides/converter.mdx +++ b/pages/aws/config/overrides/converter.mdx @@ -27,7 +27,7 @@ The `aws-cloudfront` Converter is a converter for Cloudfront (i.e. lambda@edge) The `edge` Converter is the converter for everything that uses `Request` and `Response`. At the moment with the builtin one that's only Cloudflare. -### converter +### node The `node` Converter is a converter for classic Node.js server. From b9cb56080219afc3180a8ec2a565b49ed14483e7 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:27:23 +0100 Subject: [PATCH 11/23] docs(aws): use OPEN_NEXT_BUILD_ID for cache keys - The cache and tag keys are prefixed with the OpenNext build id (deploymentId when set) - NEXT_BUILD_ID is the Next.js build id used in /_next/data URLs - Mention the automatic CDN invalidation in the caching page --- pages/aws/config/overrides/incremental_cache.mdx | 1 + pages/aws/inner_workings/caching.mdx | 14 +++++++++----- .../aws/inner_workings/components/server/node.mdx | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pages/aws/config/overrides/incremental_cache.mdx b/pages/aws/config/overrides/incremental_cache.mdx index e0cbc312..8217e82f 100644 --- a/pages/aws/config/overrides/incremental_cache.mdx +++ b/pages/aws/config/overrides/incremental_cache.mdx @@ -8,6 +8,7 @@ If you want to better understand how to implement your own IncrementalCache, the One thing to note is that it is not used at build time, only at runtime. This means that you'll have to upload the cache yourself if you want to use the prebuilt routes/pages (And this is mandatory for ISR/SSG routes with `fallback:false`). All the cache files are present in the `.open-next/cache` folder. The one under `BUILD_ID` are for the ISR/SSG cache and the one under `__fetch/BUILD_ID` are for the fetch cache. +`BUILD_ID` is the OpenNext build id (`process.env.OPEN_NEXT_BUILD_ID` at runtime): the Next.js [`deploymentId`](https://nextjs.org/docs/app/api-reference/config/next-config-js/deploymentId) when set and the Next.js build id otherwise. ## Included IncrementalCache diff --git a/pages/aws/inner_workings/caching.mdx b/pages/aws/inner_workings/caching.mdx index a3439ab6..3ae2f29e 100644 --- a/pages/aws/inner_workings/caching.mdx +++ b/pages/aws/inner_workings/caching.mdx @@ -21,7 +21,9 @@ They use this header by default `s-maxage=YOUR_REVALIDATION_TIME, stale-while-re ### Cloudfront cache invalidation -When you manually revalidate the Next.js cache for a specific page, the ISR cache files stored on S3 will be updated. However, it is still necessary to invalidate the CloudFront cache: +When you manually revalidate the Next.js cache for a specific page, the ISR cache files stored on S3 will be updated. However, it is still necessary to invalidate the CloudFront cache. + +This can be done automatically by the [Automatic CDN Invalidation](/aws/config/overrides/automatic_cdn_invalidation) override (i.e. `cdnInvalidation: "cloudfront"`). Otherwise you can invalidate the CloudFront cache manually: ```js filename="pages/api/revalidate.js" export default async function handler(req, res) { @@ -31,7 +33,7 @@ export default async function handler(req, res) { } ``` -If the pages router is in use, you must also invalidate the `_next/data/BUILD_ID/foo.json` path. The value for `BUILD_ID` can be found in the `.next/BUILD_ID` build output and can be accessed at runtime via the `process.env.NEXT_BUILD_ID` environment variable. +If the pages router is in use, you must also invalidate the `_next/data/BUILD_ID/foo.json` path. The value for `BUILD_ID` is the Next.js build id. It can be found in the `.next/BUILD_ID` build output and can be accessed at runtime via the `process.env.NEXT_BUILD_ID` environment variable. ```ts await invalidateCloudFrontPaths(["/foo", `/_next/data/${process.env.NEXT_BUILD_ID}/foo.json`]); @@ -75,7 +77,9 @@ await invalidateCloudFrontPaths(["/page/a", "/page/b", "/page/c"]); await invalidateCloudFrontPaths(["/page/*"]); ``` -For on-demand revalidation via the [`next/cache` module](https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#using-on-demand-revalidation), if you want to retrieve the associated paths for a given tag, you can use this function: +For on-demand revalidation via the [`next/cache` module](https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#using-on-demand-revalidation), if you want to retrieve the associated paths for a given tag, you can use this function. + +Note that the tags are prefixed with the OpenNext build id (`process.env.OPEN_NEXT_BUILD_ID`), which is the Next.js [`deploymentId`](https://nextjs.org/docs/app/api-reference/config/next-config-js/deploymentId) when set and the Next.js build id otherwise. ```ts import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb"; @@ -92,11 +96,11 @@ async function getPaths(tag: string) { "#tag": "tag", }, ExpressionAttributeValues: { - ":tag": { S: `${process.env.NEXT_BUILD_ID}/${tag}` }, + ":tag": { S: `${process.env.OPEN_NEXT_BUILD_ID}/${tag}` }, }, }) ); - return Items?.map((item) => item.path?.S?.replace(`${process.env.NEXT_BUILD_ID}/`, "") ?? "") ?? []; + return Items?.map((item) => item.path?.S?.replace(`${process.env.OPEN_NEXT_BUILD_ID}/`, "") ?? "") ?? []; } catch (e) { console.error("Failed to get by tag", e); return []; diff --git a/pages/aws/inner_workings/components/server/node.mdx b/pages/aws/inner_workings/components/server/node.mdx index 69287322..859371fa 100644 --- a/pages/aws/inner_workings/components/server/node.mdx +++ b/pages/aws/inner_workings/components/server/node.mdx @@ -52,6 +52,8 @@ File in S3 should follow the following structure: - `Key_Prefix/BUILD_ID/path/to/page.cache` - For the cache of a page - `Key_Prefix/__fetch/BUILD_ID/fetch-cache-key` - For the fetch cache +`BUILD_ID` is the OpenNext build id (`process.env.OPEN_NEXT_BUILD_ID`): the Next.js `deploymentId` when set and the Next.js build id otherwise. + The default S3 Incremental Cache can be configured using the following environment variables: ###### Environment Variables From d0003a1822c1e10fdc1e7aa054cc78c5a52dea39 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:27:30 +0100 Subject: [PATCH 12/23] docs(aws): document the --dangerously-use-unsupported-next-version build flag --- pages/aws/config.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pages/aws/config.mdx b/pages/aws/config.mdx index 59b8a084..366b17b8 100644 --- a/pages/aws/config.mdx +++ b/pages/aws/config.mdx @@ -1,9 +1,10 @@ ### Build Arguments -There is two build arguments that you can pass to the `open-next build` command: +These are the build arguments that you can pass to the `open-next build` command: - `--config-path` - This is the path to the configuration file that you want to use. By default, it will look for `open-next.config.ts` in the current working directory. This needs to be relative to the current working directory. - `--node-externals` - You can configure externals for the esbuild compilation of the `open-next.config.ts` file (i.e `--node-externals @aws-sdk/*,open-next/dist/queue/*`) +- `--dangerously-use-unsupported-next-version` - Since `@opennextjs/aws` 3.9.13, the build fails when the Next.js version is no longer supported by the Next.js team (see the [Next.js support policy](https://nextjs.org/support-policy)) as it may contain unpatched security vulnerabilities. This flag allows building anyway. ### Configuration File From 1e6e6e228c864ccaf6286941eacd422e2c9cbf61 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:27:49 +0100 Subject: [PATCH 13/23] docs(aws): document the filtering of non-Linux native binaries --- pages/aws/common_issues.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pages/aws/common_issues.mdx b/pages/aws/common_issues.mdx index 172c0caa..3e635cc7 100644 --- a/pages/aws/common_issues.mdx +++ b/pages/aws/common_issues.mdx @@ -32,6 +32,9 @@ You should also not add sharp as a dependency unless absolutely necessary, the i - `next/dist/compiled/babel-packages` - `next/dist/compiled/amphtml-validator` +Since `@opennextjs/aws` 3.10.0, OpenNext also excludes the platform specific native binaries for non-Linux platforms (i.e. `@swc/core-darwin-arm64`) that are traced when building on macOS or Windows. +You can set the `OPEN_NEXT_SKIP_PLATFORM_FILTER` environment variable to `true` at build time to disable this filter. + ##### Remove sourcemaps Source maps could add a lot to the bundle, excluding them from standalone output could be worth it. From b458cd83466d7a9d27c75edc77568ec3923cea71 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:27:56 +0100 Subject: [PATCH 14/23] docs(aws): document OPEN_NEXT_REQUEST_ID_HEADER and OPEN_NEXT_ERROR_LOG_LEVEL --- pages/aws/common_issues.mdx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pages/aws/common_issues.mdx b/pages/aws/common_issues.mdx index 3e635cc7..8b061201 100644 --- a/pages/aws/common_issues.mdx +++ b/pages/aws/common_issues.mdx @@ -8,6 +8,11 @@ This will output **A LOT** of additional logs to the console.This also disable m OPEN_NEXT_DEBUG=true npx open-next@latest build ``` +A few other environment variables can help debugging at runtime: + +- `OPEN_NEXT_REQUEST_ID_HEADER` - When set, the `x-opennext-requestid` header is added to the responses (it is always added in debug mode). Available since `@opennextjs/aws` 3.7.0. +- `OPEN_NEXT_ERROR_LOG_LEVEL` - The minimum level of the internal OpenNext errors that are logged: `0` (or `debug`), `1` (or `warn`, the default) or `2` (or `error`). + #### Cannot find module next You might stumble upon this error inside cloudwatch logs: `Cannot find module 'next'`. It is likely that you are in a monorepo and you have several lock files. **Just make sure that you have a single lock file in the root of your project.** From 11c23be00138f5a0919302069d128691d2b44c04 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:28:09 +0100 Subject: [PATCH 15/23] docs(aws): document the Cache-Control override for error responses --- pages/aws/inner_workings/caching.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/aws/inner_workings/caching.mdx b/pages/aws/inner_workings/caching.mdx index 3ae2f29e..695b33ad 100644 --- a/pages/aws/inner_workings/caching.mdx +++ b/pages/aws/inner_workings/caching.mdx @@ -19,6 +19,8 @@ They use this header by default `s-maxage=YOUR_REVALIDATION_TIME, stale-while-re **All of these issues are automatically fixed for you in OpenNext** +Next.js can also set a cacheable `Cache-Control` header on some error responses (i.e. `notFound()` on an ISR route). To prevent the CDN from caching a transient error for the whole revalidation period, OpenNext overrides the `Cache-Control` header of 404 and 500 responses with `private, no-cache, no-store, max-age=0, must-revalidate`. You can opt out by setting the `OPEN_NEXT_DANGEROUSLY_SET_ERROR_HEADERS` environment variable to `true`. + ### Cloudfront cache invalidation When you manually revalidate the Next.js cache for a specific page, the ISR cache files stored on S3 will be updated. However, it is still necessary to invalidate the CloudFront cache. From 8cf0bd4ef0042bf83f73a35b7789a8499a1d2081 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:28:13 +0100 Subject: [PATCH 16/23] docs(aws): mention Next.js 16 support on the home page --- pages/aws/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/aws/index.mdx b/pages/aws/index.mdx index ca5d6ab5..f23e482f 100644 --- a/pages/aws/index.mdx +++ b/pages/aws/index.mdx @@ -28,7 +28,7 @@ We need your help keeping it up to date and feature complete. Make sure to [**jo --- -OpenNext aims to support all Next.js 15 features and is widely deployed in production across multiple platforms. +OpenNext aims to support all Next.js 15 and 16 features and is widely deployed in production across multiple platforms. [NHS England](https://github.com/nhs-england-tools/terraform-aws-opennext), [Udacity](https://engineering.udacity.com/deploying-next-js-on-the-edge-with-sst-is-sst-the-game-changer-its-claimed-to-be-1f05a0abc27c), [Gymshark UK](https://uk.gymshark.com), [SST](https://sst.dev), [Cloudflare](https://www.cloudflare.com) From 0c5fa882d9f543fa70047791de8c964463ceda59 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:28:24 +0100 Subject: [PATCH 17/23] docs(aws): fix the custom asset resolver example to use a LazyLoadedOverride --- pages/aws/config/custom_overrides.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/aws/config/custom_overrides.mdx b/pages/aws/config/custom_overrides.mdx index c7c3670d..8f175e9e 100644 --- a/pages/aws/config/custom_overrides.mdx +++ b/pages/aws/config/custom_overrides.mdx @@ -418,7 +418,7 @@ import type { OpenNextConfig } from "@opennextjs/aws/types/open-next.js"; const config = { default: {}, middleware: { - assetResolver: import("./customAssetResolver").then((mod) => mod.default), + assetResolver: () => import("./customAssetResolver").then((mod) => mod.default), }, } satisfies OpenNextConfig; From f39929d20ea29ae55d68a41d89cbb1c3ff131657 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:28:29 +0100 Subject: [PATCH 18/23] docs(aws): fix the description of the cdnInvalidation override values --- pages/aws/config/reference.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx index e8d90a3e..7c4db2cc 100644 --- a/pages/aws/config/reference.mdx +++ b/pages/aws/config/reference.mdx @@ -170,7 +170,7 @@ Each server config will be under it's own key in the config object. Here are all Add possibility to override the CDN invalidation override. Used for on-demand invalidation with `revalidatePath()`, `revalidateTag()` and `res.revalidate()`. - Possible values are: `cloudfront`, `dummy` or a `LazyLoadedOverride` that will return the invalidatePaths. This override is disabled by default. + Possible values are: `cloudfront`, `dummy` or a `LazyLoadedOverride` that will return the CDN invalidation handler. This override is disabled by default (`dummy`). From 93909925ce65c61fca6f5054689e5db5509d5eee Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:28:41 +0100 Subject: [PATCH 19/23] docs(aws): update the minimum Node.js version --- pages/aws/inner_workings/components/overview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/aws/inner_workings/components/overview.mdx b/pages/aws/inner_workings/components/overview.mdx index d23d8d49..abf498ee 100644 --- a/pages/aws/inner_workings/components/overview.mdx +++ b/pages/aws/inner_workings/components/overview.mdx @@ -9,7 +9,7 @@ This is also mostly for advanced use cases (Overriding some default, provide sup ## General -- For the node runtime, you need at least Node 18. +- For the node runtime, you need a Node.js version supported by your version of Next.js (Node.js 20.9+ for Next.js 16, Node.js 18.18+ for Next.js 15). - For the edge runtime, you can use both Node 18+ or cloudflare workers with `node_compat` flag enabled (Cloudflare workers support is experimental) - Open-next doesn't work well on Windows. We recommend using WSL2 or a Linux VM. From 55ffb52e2e389010b9e9211b403d6df6583051db Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 5 Nov 2026 10:28:57 +0100 Subject: [PATCH 20/23] docs(aws): fix broken links --- pages/aws/inner_workings.mdx | 2 +- pages/aws/migration.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/aws/inner_workings.mdx b/pages/aws/inner_workings.mdx index f1488d99..61049c69 100644 --- a/pages/aws/inner_workings.mdx +++ b/pages/aws/inner_workings.mdx @@ -2,7 +2,7 @@ When calling `open-next build`, OpenNext **runs `next build`** to build the Next #### Building the Next.js app -OpenNext runs the `build` script in your `package.json` file. Depending on the lock file found in the app, the corresponding packager manager will be used. Either `npm run build`, `yarn build`, or `pnpm build` will be run. For more on customizing the build command, see [overriding the build command](/aws/advanced/options#custom-build-command). +OpenNext runs the `build` script in your `package.json` file. Depending on the lock file found in the app, the corresponding packager manager will be used. Either `npm run build`, `yarn build`, or `pnpm build` will be run. For more on customizing the build command, see [the `buildCommand` option](/aws/config/reference). #### Transforming the build output diff --git a/pages/aws/migration.mdx b/pages/aws/migration.mdx index f1b0d2d3..178e7c99 100644 --- a/pages/aws/migration.mdx +++ b/pages/aws/migration.mdx @@ -21,7 +21,7 @@ Here are the old build args and their new equivalent: Everything should already be set up for you. But there are a few things you should know: -- Streaming by default is disabled in open-next (for now). It is very **experimental** right now see [here](/aws/inner_workings/streaming) for more info. +- Streaming is disabled by default in OpenNext. To enable it in AWS Lambda, use the `aws-lambda-streaming` or `aws-apigw-streaming` [wrapper](/aws/config/overrides/wrapper). - Middleware is not run for static file and for image requests with open-next. #### AWS Amplify From fcef760fe5de2684f6075c0cea2caf7df5b375e4 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 13 Nov 2026 07:38:11 +0100 Subject: [PATCH 21/23] docs(aws): document when Queue.send is called and when it should resolve --- pages/aws/config/overrides/queue.mdx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pages/aws/config/overrides/queue.mdx b/pages/aws/config/overrides/queue.mdx index 9f8a3ddf..53cd61d4 100644 --- a/pages/aws/config/overrides/queue.mdx +++ b/pages/aws/config/overrides/queue.mdx @@ -1,13 +1,17 @@ import { Callout } from "nextra/components"; This override is used by OpenNext to trigger the revalidation of stale routes. -Before sending the response to the client, OpenNext will check if the route is stale and if it is, it will call the queue override to revalidate the route. +When a stale route is served, OpenNext calls the `send` method of the queue override to revalidate the route: + +- When the route is rendered by the Next server, `send` is called once the response is sent (in `waitUntil` when the wrapper provides one). +- With [cache interception](/aws/inner_workings/cache_interception), `send` is awaited before the stale response is returned. If it throws, the error is logged and the request falls back to the Next server. If you want to better understand how to implement your own Queue, the easiest way would be to take a look at the existing [included Queue](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/queue). Couple of things to note : - The default implementation use an SQS queue. This has the main advantage of being able to control the concurrency of the revalidations as well as avoiding trigerring the revalidation multiple times for the same route. +- The promise returned by `send` should resolve once the message is accepted (or handed to `waitUntil`), not once the route is revalidated, so that the response is not delayed. - You don't have to use a queue at all. You could trigger the revalidation directly in the Queue override itself. You can see a very simple implementation of this [in the `direct` override](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/queue/direct.ts). ## Included Queue @@ -37,7 +41,9 @@ This implementation is a lighter version of the `sqs` Queue as it uses `aws4fetc The Direct Queue will directly trigger the revalidation of the route in the Queue override itself. It is useful for development purposes and when you don't want to use a queue. - Be careful with this implementation as it could lead to multiple revalidations of the same route. + Be careful with this implementation as it could lead to multiple revalidations of the same route. As `send` + resolves once the route is revalidated, it also delays the stale response when cache interception is + enabled. ### dummy From 1dd8f774ed6ca655d230c62392f13d563797ee1a Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 13 Nov 2026 07:38:27 +0100 Subject: [PATCH 22/23] docs(aws): document lastModified and eTag in the revalidation queue message --- pages/aws/inner_workings/components/server/node.mdx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pages/aws/inner_workings/components/server/node.mdx b/pages/aws/inner_workings/components/server/node.mdx index 859371fa..85035f52 100644 --- a/pages/aws/inner_workings/components/server/node.mdx +++ b/pages/aws/inner_workings/components/server/node.mdx @@ -112,6 +112,9 @@ interface QueueMessage { MessageBody: { host: string; url: string; + // Time of the cache entry (ms since epoch) + lastModified: number; + eTag: string; }; MessageGroupId: string; } @@ -122,7 +125,9 @@ export interface Queue { } ``` -The send function will be called when a page is marked as `STALE`. You don't have to use a queue here, you can use any other mechanism to send the message to the revalidation worker or even do the revalidation in the same process. +The send function will be called when a page is marked as `STALE`. + +`MessageBody.lastModified` is the time of the cache entry, so a queue can skip the messages for entries that were revalidated since. Before `@opennextjs/aws` 4.1.16, it was `1` for pages made stale by `revalidateTag`. `MessageDeduplicationId` is derived from the path, the `ETag` and the time of the entry (`1` for every entry made stale by a tag, so that they are deduplicated). You don't have to use a queue here, you can use any other mechanism to send the message to the revalidation worker or even do the revalidation in the same process. #### Shared Environment Variables From f2cd7b8b99077344530b3761989a7ed4dd181e8c Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 13 Nov 2026 10:15:50 +0100 Subject: [PATCH 23/23] docs(aws): clarify that deploymentId is used as the build id for every Next.js version --- pages/aws/config/overrides/incremental_cache.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/pages/aws/config/overrides/incremental_cache.mdx b/pages/aws/config/overrides/incremental_cache.mdx index 8217e82f..2967ad17 100644 --- a/pages/aws/config/overrides/incremental_cache.mdx +++ b/pages/aws/config/overrides/incremental_cache.mdx @@ -9,6 +9,7 @@ If you want to better understand how to implement your own IncrementalCache, the One thing to note is that it is not used at build time, only at runtime. This means that you'll have to upload the cache yourself if you want to use the prebuilt routes/pages (And this is mandatory for ISR/SSG routes with `fallback:false`). All the cache files are present in the `.open-next/cache` folder. The one under `BUILD_ID` are for the ISR/SSG cache and the one under `__fetch/BUILD_ID` are for the fetch cache. `BUILD_ID` is the OpenNext build id (`process.env.OPEN_NEXT_BUILD_ID` at runtime): the Next.js [`deploymentId`](https://nextjs.org/docs/app/api-reference/config/next-config-js/deploymentId) when set and the Next.js build id otherwise. +This applies to every supported Next.js version. It matters most on Next.js 16.2+, where the Next.js build id is the same for every deployment when `deploymentId` is set. ## Included IncrementalCache