Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion src/content/docs/en/guides/integrations-guide/node.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,69 @@ export default defineConfig({
});
```

### `shutdown`

<p>
**Type:** `{ timeout?: number; exit?: boolean }` <br />
**Default:** `{ timeout: 10000, exit: false }`<br />
<Since pkg="@astrojs/node" v="11.2.0" />
</p>

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,
},
}),
});
```

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved your the nested properties description to their own subheadings. And I tried to tighten a bit the wording to be more direct. Feel free to tell if any important information is missing.

Suggested change
#### `shutdown.timeout`
<p>
**Type:** `number`<br />
**Default:** `10000`
</p>
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`
<p>
**Type:** `boolean`<br />
**Default:** `false`
</p>
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 first. Set to `true` to force the process to exit even if open timers or connections remain.

#### `shutdown.timeout`

<p>
**Type:** `number`<br />
**Default:** `10000`
</p>

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`

<p>
**Type:** `boolean`<br />
**Default:** `false`
</p>

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:
Expand Down Expand Up @@ -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"]

@WhatCats WhatCats Sep 21, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exec form so Node runs as PID 1 and receives SIGTERM directly.

```
</TabItem>
</Tabs>
Loading