diff --git a/src/content/docs/en/guides/integrations-guide/node.mdx b/src/content/docs/en/guides/integrations-guide/node.mdx index 7acd298fe0b16..1b25746327b45 100644 --- a/src/content/docs/en/guides/integrations-guide/node.mdx +++ b/src/content/docs/en/guides/integrations-guide/node.mdx @@ -185,6 +185,69 @@ export default defineConfig({ }); ``` +### `shutdown` + +

+**Type:** `{ timeout?: number; exit?: boolean }`
+**Default:** `{ timeout: 10000, exit: false }`
+ +

+ +Controls graceful shutdown behavior of the [`standalone`](#mode) server when it receives a `SIGTERM` or `SIGINT` signal (e.g. when a host stops or restarts the process). The server stops accepting new connections but waits for active requests to finish before closing. + +The following example configures a 30-second shutdown timeout and forces the process to exit once the shutdown is complete: + +```js title="astro.config.mjs" {7-10} +import { defineConfig } from 'astro/config'; +import node from '@astrojs/node'; + +export default defineConfig({ + adapter: node({ + mode: 'standalone', + shutdown: { + timeout: 30 * 1000, // wait up to 30 seconds + exit: true, + }, + }), +}); +``` + +#### `shutdown.timeout` + +

+**Type:** `number`
+**Default:** `10000` +

+ +The duration in milliseconds to wait for active requests to finish before force-closing remaining connections. Set to `0` to force-close immediately, or `Infinity` to wait indefinitely. + +#### `shutdown.exit` + +

+**Type:** `boolean`
+**Default:** `false` +

+ +Controls whether to call `process.exit()` once shutdown completes. By default, the process exits naturally when the event loop is empty, allowing other signal listeners (e.g. database disconnect handlers) to finish before closing. Set to `true` to force the process to exit even if open timers or connections remain. + +If the process does not exit after receiving a shutdown signal, check the adapter's logs for a `Shutdown complete.` message. This confirms that the server itself closed successfully, so something else in the process is keeping the event loop active. + +Register a separate [`SIGTERM`/`SIGINT` listener](https://nodejs.org/api/process.html#signal-events) in the application to close any other open resources, such as a database connection, when the server shuts down: + +```js +process.on('SIGINT', () => db.close()); +process.on('SIGTERM', () => db.close()); +``` + +A `setInterval()` or `setTimeout()` also keeps the event loop open, and therefore the process running. This is often unintentional. Call `.unref()` on the timer so it does not block shutdown: + +```js +setInterval(() => {}, 1000).unref(); +setTimeout(() => {}, 1000).unref(); +``` + +To avoid tracking down every open resource, set `exit` to `true` and let the adapter force the process to exit once its own shutdown completes. + ## Usage First, [performing a build](/en/guides/deploy/#building-your-site-locally). Depending on which `mode` selected (see above) follow the appropriate steps below: @@ -328,7 +391,7 @@ When self-hosting, you can load environment variables through CLI commands or co ENV DB_HOST=... ENV DB_PASSWORD=... - CMD node ./dist/server/entry.mjs + CMD ["node", "./dist/server/entry.mjs"] ```