From cb3eedd4b6ebbd90c2c62f53052a2d7c437f168f Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sat, 10 Oct 2026 08:00:53 -0600 Subject: [PATCH 1/7] Document threads.v8Flags Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VKZAtTiprHW8Sp1Ff4hGAZ Dispatch-Task: harper-threads-v8flags --- reference/configuration/options.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/reference/configuration/options.md b/reference/configuration/options.md index 837c0b61..27684a42 100644 --- a/reference/configuration/options.md +++ b/reference/configuration/options.md @@ -68,6 +68,7 @@ threads: - `debug` — Enable Node.js inspector; sub-options: `port`, `startingPort`, `host`, `waitForDebugger`. See [Worker Thread Debugging](./debugging.md) - `preload` — Module, or list of modules, to load via Node's `--import` before any Harper or application module on each worker thread. Intended for instrumentation and APM agents. Worker threads only (not under Bun). - `preloadRequire` — The same, but via Node's `--require` (CommonJS). Worker threads only (not under Bun). +- `v8Flags` — V8 flag, or list of V8 flags, applied to the whole Harper process before its first worker thread starts. Each entry must start with `--`. Takes effect on process start. Not applied under Bun. See [Applying V8 flags](#applying-v8-flags) ### Preloading an instrumentation agent @@ -105,6 +106,24 @@ threads: The dd-trace behavior described here was observed on 6.x. Check your agent's current documentation, and confirm your spans arrive at your collector. +### Applying V8 flags + +Some V8 flags, such as `--optimize-for-size`, cannot be passed through `NODE_OPTIONS` (Node refuses them there) or to a worker thread. `v8Flags` applies them inside Harper instead: the main thread calls Node's [`v8.setFlagsFromString()`](https://nodejs.org/api/v8.html#v8setflagsfromstringflags) for each entry before the first worker thread starts, so every worker thread runs with them. V8 flags are process-wide, so the main thread runs with them from that point on too. + +```yaml +threads: + v8Flags: + - --optimize-for-size + - --max-semi-space-size=1 +``` + +The value can also be set from the environment, for example `HARPER_SET_CONFIG='{"threads":{"v8Flags":["--optimize-for-size"]}}'`. + +- **Validation.** An entry that does not start with `--` stops Harper at startup with an error naming `threads.v8Flags`. V8 skips a flag it does not recognize and only prints `Error: unrecognized flag` to standard error, so check the spelling against your Node version (`node --v8-options`). +- **Implied flags are not applied.** On the command line, some flags turn on others; `--optimize-for-size` also caps the young-generation semi-space at 1 MB. Applied at runtime, a flag does not do that, so list the implied flags explicitly, as the example does with `--max-semi-space-size=1`. +- **When it takes effect.** Flags are read once per process. A changed value takes effect on the next full restart (`harper restart` or a process restart), not on a worker thread restart. Removing the setting and restarting is how to roll it back. +- **Expert setting.** Flags change V8's behavior for the whole process and are not validated beyond the `--` prefix. A conflicting combination can stop the process at startup. Measure memory and throughput with your workload before relying on a flag in production. + --- ## `authentication` From 897dcca8b08a67b52f32986b203419402ed74cde Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sat, 10 Oct 2026 08:26:24 -0600 Subject: [PATCH 2/7] Clarify threads.v8Flags validation and main-thread effect Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VKZAtTiprHW8Sp1Ff4hGAZ Dispatch-Task: harper-threads-v8flags --- reference/configuration/options.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/configuration/options.md b/reference/configuration/options.md index 27684a42..a79db442 100644 --- a/reference/configuration/options.md +++ b/reference/configuration/options.md @@ -108,7 +108,7 @@ The dd-trace behavior described here was observed on 6.x. Check your agent's cur ### Applying V8 flags -Some V8 flags, such as `--optimize-for-size`, cannot be passed through `NODE_OPTIONS` (Node refuses them there) or to a worker thread. `v8Flags` applies them inside Harper instead: the main thread calls Node's [`v8.setFlagsFromString()`](https://nodejs.org/api/v8.html#v8setflagsfromstringflags) for each entry before the first worker thread starts, so every worker thread runs with them. V8 flags are process-wide, so the main thread runs with them from that point on too. +Some V8 flags, such as `--optimize-for-size`, cannot be passed through `NODE_OPTIONS` (Node refuses them there) or to a worker thread. `v8Flags` applies them inside Harper instead: the main thread calls Node's [`v8.setFlagsFromString()`](https://nodejs.org/api/v8.html#v8setflagsfromstringflags) for each entry before the first worker thread starts, so every worker thread runs with them. V8 flags are process-wide, so they also affect the main thread from that point on. The main thread's isolate already exists, though, so flags V8 reads only when an isolate is created (such as heap sizing) do not change it. With `count: 0`, where the main thread serves requests, those flags have no effect. ```yaml threads: @@ -119,7 +119,7 @@ threads: The value can also be set from the environment, for example `HARPER_SET_CONFIG='{"threads":{"v8Flags":["--optimize-for-size"]}}'`. -- **Validation.** An entry that does not start with `--` stops Harper at startup with an error naming `threads.v8Flags`. V8 skips a flag it does not recognize and only prints `Error: unrecognized flag` to standard error, so check the spelling against your Node version (`node --v8-options`). +- **Validation.** Surrounding whitespace is trimmed, and an empty entry is ignored. An entry that does not start with `--` is refused by `set_configuration`, and stops Harper at startup with an error naming `threads.v8Flags`. V8 skips a flag it does not recognize and only prints `Error: unrecognized flag` to standard error, so check the spelling against your Node version (`node --v8-options`). - **Implied flags are not applied.** On the command line, some flags turn on others; `--optimize-for-size` also caps the young-generation semi-space at 1 MB. Applied at runtime, a flag does not do that, so list the implied flags explicitly, as the example does with `--max-semi-space-size=1`. - **When it takes effect.** Flags are read once per process. A changed value takes effect on the next full restart (`harper restart` or a process restart), not on a worker thread restart. Removing the setting and restarting is how to roll it back. - **Expert setting.** Flags change V8's behavior for the whole process and are not validated beyond the `--` prefix. A conflicting combination can stop the process at startup. Measure memory and throughput with your workload before relying on a flag in production. From 2dfc09660fef570e5951a0af679258716fd67316 Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sat, 10 Oct 2026 08:43:02 -0600 Subject: [PATCH 3/7] Add threads.v8Flags to the 5.4 release notes Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VKZAtTiprHW8Sp1Ff4hGAZ Dispatch-Task: harper-threads-v8flags --- release-notes/v5-lincoln/5.4.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/release-notes/v5-lincoln/5.4.md b/release-notes/v5-lincoln/5.4.md index e684c1b5..1c3f8ee5 100644 --- a/release-notes/v5-lincoln/5.4.md +++ b/release-notes/v5-lincoln/5.4.md @@ -51,3 +51,9 @@ A `deploy_component` with `restart: true` or `restart: "rolling"` now checks its ### Setting Up GitHub Actions Deploys `harper deploy setup=true provider=github-actions` sets a cluster up so a GitHub Actions workflow can deploy with its OIDC identity token instead of a stored credential. It creates a deploy-only role and user, a trust policy matching the workflow's repository, branch and environment, and the repository's `HARPER_CLI_TARGET` variable. It checks the policy against the workflow file in the repository's checkout before it writes, where it can, and reads it back after. It only creates: running it again leaves the cluster and the variable as they are, a record that differs, or that someone deactivated or disabled, stops it before it writes, and a `HARPER_CLI_TARGET` that names another cluster is left in place. A policy with the same id that another super user creates in the moment before setup writes it is still overwritten. See [GitHub Actions deploys (OIDC)](/reference/v5/cli/commands#github-actions-deploys-oidc). + +## Configuration + +### Applying V8 Flags From the Configuration + +The new `threads.v8Flags` setting takes a V8 flag, or a list of them, and applies them to the Harper process before its first worker thread starts, so every worker thread runs with them. It is for flags such as `--optimize-for-size`, which Node refuses in `NODE_OPTIONS` and which cannot be passed to a worker thread. It can also be set through `HARPER_SET_CONFIG` or `HARPER_CONFIG`. An entry must start with `--`; `set_configuration` refuses one that does not, and Harper stops at startup with an error naming the setting. Unlike the command line, this does not apply a flag's implied flags, so list them yourself (for example `--max-semi-space-size=1` alongside `--optimize-for-size`). A changed value takes effect on the next full restart. Not applied under Bun. See [Applying V8 flags](/reference/v5/configuration/options#applying-v8-flags). From c6fe0283c3c9a335f397dc696cf9af421b8ded58 Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sat, 10 Oct 2026 09:23:17 -0600 Subject: [PATCH 4/7] Say which restart applies threads.v8Flags, here and on the set_configuration pages Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VKZAtTiprHW8Sp1Ff4hGAZ Dispatch-Task: harper-threads-v8flags --- reference/configuration/operations.md | 2 +- reference/configuration/options.md | 6 +++--- reference/operations-api/operations.md | 2 +- release-notes/v5-lincoln/5.4.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/configuration/operations.md b/reference/configuration/operations.md index 38c20edd..24276ac0 100644 --- a/reference/configuration/operations.md +++ b/reference/configuration/operations.md @@ -72,7 +72,7 @@ The `replicated` array reports per-node outcomes. A failed peer appears as `{ "s } ``` -To restart the whole cluster afterward, follow with [restart_service](../operations-api/operations.md#restart_service) using `"replicated": true` — it restarts nodes one at a time, so the cluster stays available: +To restart the whole cluster afterward, follow with [restart_service](../operations-api/operations.md#restart_service) using `"replicated": true` — it restarts nodes one at a time, so the cluster stays available. `restart_service` restarts only worker threads, so a change to [`threads.v8Flags`](./options.md#applying-v8-flags) needs a [restart](../operations-api/operations.md#restart) of each node instead: ```json { diff --git a/reference/configuration/options.md b/reference/configuration/options.md index a79db442..2f064b6a 100644 --- a/reference/configuration/options.md +++ b/reference/configuration/options.md @@ -108,7 +108,7 @@ The dd-trace behavior described here was observed on 6.x. Check your agent's cur ### Applying V8 flags -Some V8 flags, such as `--optimize-for-size`, cannot be passed through `NODE_OPTIONS` (Node refuses them there) or to a worker thread. `v8Flags` applies them inside Harper instead: the main thread calls Node's [`v8.setFlagsFromString()`](https://nodejs.org/api/v8.html#v8setflagsfromstringflags) for each entry before the first worker thread starts, so every worker thread runs with them. V8 flags are process-wide, so they also affect the main thread from that point on. The main thread's isolate already exists, though, so flags V8 reads only when an isolate is created (such as heap sizing) do not change it. With `count: 0`, where the main thread serves requests, those flags have no effect. +Some V8 flags, such as `--optimize-for-size`, cannot be passed through `NODE_OPTIONS` (Node refuses them there) or to a worker thread. `v8Flags` applies them inside Harper instead: the main thread calls Node's [`v8.setFlagsFromString()`](https://nodejs.org/api/v8.html#v8setflagsfromstringflags) for each entry before the first worker thread starts, so every worker thread runs with them. V8 flags are process-wide, so they also affect the main thread from that point on. The main thread's isolate already exists, though, so flags V8 reads only when an isolate is created (such as heap sizing) do not change it. With `count: 0`, the main thread serves requests, so those creation-time flags do not affect request handling; flags V8 reads while running still apply. ```yaml threads: @@ -117,11 +117,11 @@ threads: - --max-semi-space-size=1 ``` -The value can also be set from the environment, for example `HARPER_SET_CONFIG='{"threads":{"v8Flags":["--optimize-for-size"]}}'`. +The value can also be set from the environment, for example `HARPER_SET_CONFIG='{"threads":{"v8Flags":["--optimize-for-size","--max-semi-space-size=1"]}}'`. - **Validation.** Surrounding whitespace is trimmed, and an empty entry is ignored. An entry that does not start with `--` is refused by `set_configuration`, and stops Harper at startup with an error naming `threads.v8Flags`. V8 skips a flag it does not recognize and only prints `Error: unrecognized flag` to standard error, so check the spelling against your Node version (`node --v8-options`). - **Implied flags are not applied.** On the command line, some flags turn on others; `--optimize-for-size` also caps the young-generation semi-space at 1 MB. Applied at runtime, a flag does not do that, so list the implied flags explicitly, as the example does with `--max-semi-space-size=1`. -- **When it takes effect.** Flags are read once per process. A changed value takes effect on the next full restart (`harper restart` or a process restart), not on a worker thread restart. Removing the setting and restarting is how to roll it back. +- **When it takes effect.** Flags are read once per process. A changed value takes effect when the whole process restarts: the [`restart`](../operations-api/operations.md#restart) operation, `harper restart`, or a container restart. [`restart_service`](../operations-api/operations.md#restart_service) restarts only worker threads, which keep the process's flags, so it does not apply a change, even with `"replicated": true`. To roll back, remove the setting from wherever it was set (the config file, `HARPER_SET_CONFIG`, `HARPER_CONFIG` or the `THREADS_V8FLAGS` environment variable) and restart the process. - **Expert setting.** Flags change V8's behavior for the whole process and are not validated beyond the `--` prefix. A conflicting combination can stop the process at startup. Measure memory and throughput with your workload before relying on a flag in production. --- diff --git a/reference/operations-api/operations.md b/reference/operations-api/operations.md index 2911fb92..69961a44 100644 --- a/reference/operations-api/operations.md +++ b/reference/operations-api/operations.md @@ -1688,7 +1688,7 @@ Detailed documentation: [Configuration Overview](../configuration/overview.md) Updates configuration parameters in `harper-config.yaml`. A restart (`restart` or `restart_service`) is required for changes to take effect. -Supports `"replicated": true` to apply the same change to all cluster nodes in one call; per-node outcomes are returned in the response's `replicated` array. Only send cluster-appropriate parameters when replicating — node-local parameters (ports, `node.hostname`, file paths, TLS material, `replication.hostname`/`url`/`routes`) would overwrite every peer's local values. To apply the change cluster-wide, follow with `restart_service` using `"replicated": true` (which restarts nodes one at a time). See [Configuration Operations](../configuration/operations.md#set-configuration) for details. +Supports `"replicated": true` to apply the same change to all cluster nodes in one call; per-node outcomes are returned in the response's `replicated` array. Only send cluster-appropriate parameters when replicating — node-local parameters (ports, `node.hostname`, file paths, TLS material, `replication.hostname`/`url`/`routes`) would overwrite every peer's local values. To apply the change cluster-wide, follow with `restart_service` using `"replicated": true` (which restarts nodes one at a time); a change to [`threads.v8Flags`](../configuration/options.md#applying-v8-flags) needs `restart` instead, because `restart_service` restarts only worker threads. See [Configuration Operations](../configuration/operations.md#set-configuration) for details. ```json { diff --git a/release-notes/v5-lincoln/5.4.md b/release-notes/v5-lincoln/5.4.md index 1c3f8ee5..cc632872 100644 --- a/release-notes/v5-lincoln/5.4.md +++ b/release-notes/v5-lincoln/5.4.md @@ -56,4 +56,4 @@ A `deploy_component` with `restart: true` or `restart: "rolling"` now checks its ### Applying V8 Flags From the Configuration -The new `threads.v8Flags` setting takes a V8 flag, or a list of them, and applies them to the Harper process before its first worker thread starts, so every worker thread runs with them. It is for flags such as `--optimize-for-size`, which Node refuses in `NODE_OPTIONS` and which cannot be passed to a worker thread. It can also be set through `HARPER_SET_CONFIG` or `HARPER_CONFIG`. An entry must start with `--`; `set_configuration` refuses one that does not, and Harper stops at startup with an error naming the setting. Unlike the command line, this does not apply a flag's implied flags, so list them yourself (for example `--max-semi-space-size=1` alongside `--optimize-for-size`). A changed value takes effect on the next full restart. Not applied under Bun. See [Applying V8 flags](/reference/v5/configuration/options#applying-v8-flags). +The new `threads.v8Flags` setting takes a V8 flag, or a list of them, and applies them to the Harper process before its first worker thread starts, so every worker thread runs with them. It is for flags such as `--optimize-for-size`, which Node refuses in `NODE_OPTIONS` and which cannot be passed to a worker thread. It can also be set through `HARPER_SET_CONFIG` or `HARPER_CONFIG`. An entry must start with `--`; `set_configuration` refuses one that does not, and Harper stops at startup with an error naming the setting. Unlike the command line, this does not apply a flag's implied flags, so list them yourself (for example `--max-semi-space-size=1` alongside `--optimize-for-size`). A changed value takes effect when the process restarts (`restart` or `harper restart`); `restart_service` restarts only worker threads and does not apply it. Not applied under Bun. See [Applying V8 flags](/reference/v5/configuration/options#applying-v8-flags). From 834241bf5c25de267aa2fcadd99cfda6ce6ab5cd Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sat, 10 Oct 2026 09:31:03 -0600 Subject: [PATCH 5/7] Name the restart operation, per node, as what applies a threads.v8Flags change Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VKZAtTiprHW8Sp1Ff4hGAZ Dispatch-Task: harper-threads-v8flags --- reference/configuration/operations.md | 6 ++++-- reference/configuration/options.md | 2 +- reference/operations-api/operations.md | 2 +- release-notes/v5-lincoln/5.4.md | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/reference/configuration/operations.md b/reference/configuration/operations.md index 24276ac0..75d9ed69 100644 --- a/reference/configuration/operations.md +++ b/reference/configuration/operations.md @@ -16,7 +16,7 @@ For the full list of configurable options, see [Configuration Options](./options ## Set Configuration -Modifies one or more Harper configuration parameters. **Requires a [restart](../operations-api/operations.md#restart) or [restart_service](../operations-api/operations.md#restart_service) to take effect.** A change to `replication.threads` takes effect only on a full `restart`. +Modifies one or more Harper configuration parameters. **Requires a [restart](../operations-api/operations.md#restart) or [restart_service](../operations-api/operations.md#restart_service) to take effect** (a [restart](../operations-api/operations.md#restart) for `threads.v8Flags`). A change to `replication.threads` takes effect only on a full `restart`. `operation` _(required)_ — must be `set_configuration` @@ -72,7 +72,7 @@ The `replicated` array reports per-node outcomes. A failed peer appears as `{ "s } ``` -To restart the whole cluster afterward, follow with [restart_service](../operations-api/operations.md#restart_service) using `"replicated": true` — it restarts nodes one at a time, so the cluster stays available. `restart_service` restarts only worker threads, so a change to [`threads.v8Flags`](./options.md#applying-v8-flags) needs a [restart](../operations-api/operations.md#restart) of each node instead: +To restart the whole cluster afterward, follow with [restart_service](../operations-api/operations.md#restart_service) using `"replicated": true` — it restarts nodes one at a time, so the cluster stays available: ```json { @@ -82,6 +82,8 @@ To restart the whole cluster afterward, follow with [restart_service](../operati } ``` +`restart_service` restarts only worker threads, which keep the process's V8 flags. A change to [`threads.v8Flags`](./options.md#applying-v8-flags) takes effect only after a [restart](../operations-api/operations.md#restart), sent to each node in turn. + --- ## Get Configuration diff --git a/reference/configuration/options.md b/reference/configuration/options.md index 2f064b6a..7c1787de 100644 --- a/reference/configuration/options.md +++ b/reference/configuration/options.md @@ -121,7 +121,7 @@ The value can also be set from the environment, for example `HARPER_SET_CONFIG=' - **Validation.** Surrounding whitespace is trimmed, and an empty entry is ignored. An entry that does not start with `--` is refused by `set_configuration`, and stops Harper at startup with an error naming `threads.v8Flags`. V8 skips a flag it does not recognize and only prints `Error: unrecognized flag` to standard error, so check the spelling against your Node version (`node --v8-options`). - **Implied flags are not applied.** On the command line, some flags turn on others; `--optimize-for-size` also caps the young-generation semi-space at 1 MB. Applied at runtime, a flag does not do that, so list the implied flags explicitly, as the example does with `--max-semi-space-size=1`. -- **When it takes effect.** Flags are read once per process. A changed value takes effect when the whole process restarts: the [`restart`](../operations-api/operations.md#restart) operation, `harper restart`, or a container restart. [`restart_service`](../operations-api/operations.md#restart_service) restarts only worker threads, which keep the process's flags, so it does not apply a change, even with `"replicated": true`. To roll back, remove the setting from wherever it was set (the config file, `HARPER_SET_CONFIG`, `HARPER_CONFIG` or the `THREADS_V8FLAGS` environment variable) and restart the process. +- **When it takes effect.** Flags are read once per process. A changed value takes effect when the whole process restarts: the [`restart`](../operations-api/operations.md#restart) operation, which restarts only the node that receives it, or a process or container restart. [`restart_service`](../operations-api/operations.md#restart_service) restarts only worker threads, which keep the process's flags, so it does not apply a change, even with `"replicated": true`. To roll back, remove the setting from wherever it was set (the config file, `HARPER_SET_CONFIG`, `HARPER_CONFIG` or the `THREADS_V8FLAGS` environment variable) and restart the process. - **Expert setting.** Flags change V8's behavior for the whole process and are not validated beyond the `--` prefix. A conflicting combination can stop the process at startup. Measure memory and throughput with your workload before relying on a flag in production. --- diff --git a/reference/operations-api/operations.md b/reference/operations-api/operations.md index 69961a44..b31687fb 100644 --- a/reference/operations-api/operations.md +++ b/reference/operations-api/operations.md @@ -1688,7 +1688,7 @@ Detailed documentation: [Configuration Overview](../configuration/overview.md) Updates configuration parameters in `harper-config.yaml`. A restart (`restart` or `restart_service`) is required for changes to take effect. -Supports `"replicated": true` to apply the same change to all cluster nodes in one call; per-node outcomes are returned in the response's `replicated` array. Only send cluster-appropriate parameters when replicating — node-local parameters (ports, `node.hostname`, file paths, TLS material, `replication.hostname`/`url`/`routes`) would overwrite every peer's local values. To apply the change cluster-wide, follow with `restart_service` using `"replicated": true` (which restarts nodes one at a time); a change to [`threads.v8Flags`](../configuration/options.md#applying-v8-flags) needs `restart` instead, because `restart_service` restarts only worker threads. See [Configuration Operations](../configuration/operations.md#set-configuration) for details. +Supports `"replicated": true` to apply the same change to all cluster nodes in one call; per-node outcomes are returned in the response's `replicated` array. Only send cluster-appropriate parameters when replicating — node-local parameters (ports, `node.hostname`, file paths, TLS material, `replication.hostname`/`url`/`routes`) would overwrite every peer's local values. To apply the change cluster-wide, follow with `restart_service` using `"replicated": true` (which restarts nodes one at a time); `restart_service` restarts only worker threads, though, so a change to [`threads.v8Flags`](../configuration/options.md#applying-v8-flags) takes effect only after a `restart` sent to each node in turn (`restart` does not replicate). See [Configuration Operations](../configuration/operations.md#set-configuration) for details. ```json { diff --git a/release-notes/v5-lincoln/5.4.md b/release-notes/v5-lincoln/5.4.md index cc632872..e1f63819 100644 --- a/release-notes/v5-lincoln/5.4.md +++ b/release-notes/v5-lincoln/5.4.md @@ -56,4 +56,4 @@ A `deploy_component` with `restart: true` or `restart: "rolling"` now checks its ### Applying V8 Flags From the Configuration -The new `threads.v8Flags` setting takes a V8 flag, or a list of them, and applies them to the Harper process before its first worker thread starts, so every worker thread runs with them. It is for flags such as `--optimize-for-size`, which Node refuses in `NODE_OPTIONS` and which cannot be passed to a worker thread. It can also be set through `HARPER_SET_CONFIG` or `HARPER_CONFIG`. An entry must start with `--`; `set_configuration` refuses one that does not, and Harper stops at startup with an error naming the setting. Unlike the command line, this does not apply a flag's implied flags, so list them yourself (for example `--max-semi-space-size=1` alongside `--optimize-for-size`). A changed value takes effect when the process restarts (`restart` or `harper restart`); `restart_service` restarts only worker threads and does not apply it. Not applied under Bun. See [Applying V8 flags](/reference/v5/configuration/options#applying-v8-flags). +The new `threads.v8Flags` setting takes a V8 flag, or a list of them, and applies them to the Harper process before its first worker thread starts, so every worker thread runs with them. It is for flags such as `--optimize-for-size`, which Node refuses in `NODE_OPTIONS` and which cannot be passed to a worker thread. It can also be set through `HARPER_SET_CONFIG` or `HARPER_CONFIG`. An entry must start with `--`; `set_configuration` refuses one that does not, and Harper stops at startup with an error naming the setting. Unlike the command line, this does not apply a flag's implied flags, so list them yourself (for example `--max-semi-space-size=1` alongside `--optimize-for-size`). A changed value takes effect when the process restarts (the `restart` operation, on each node); `restart_service` restarts only worker threads and does not apply it. Not applied under Bun. See [Applying V8 flags](/reference/v5/configuration/options#applying-v8-flags). From 3570a4a64bb4b413139a87b6109f625cc9b5ad17 Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sat, 10 Oct 2026 09:35:53 -0600 Subject: [PATCH 6/7] Say that an env-set threads.v8Flags persists in harper-config.yaml Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VKZAtTiprHW8Sp1Ff4hGAZ Dispatch-Task: harper-threads-v8flags --- reference/configuration/options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/configuration/options.md b/reference/configuration/options.md index 7c1787de..accc09ea 100644 --- a/reference/configuration/options.md +++ b/reference/configuration/options.md @@ -121,7 +121,7 @@ The value can also be set from the environment, for example `HARPER_SET_CONFIG=' - **Validation.** Surrounding whitespace is trimmed, and an empty entry is ignored. An entry that does not start with `--` is refused by `set_configuration`, and stops Harper at startup with an error naming `threads.v8Flags`. V8 skips a flag it does not recognize and only prints `Error: unrecognized flag` to standard error, so check the spelling against your Node version (`node --v8-options`). - **Implied flags are not applied.** On the command line, some flags turn on others; `--optimize-for-size` also caps the young-generation semi-space at 1 MB. Applied at runtime, a flag does not do that, so list the implied flags explicitly, as the example does with `--max-semi-space-size=1`. -- **When it takes effect.** Flags are read once per process. A changed value takes effect when the whole process restarts: the [`restart`](../operations-api/operations.md#restart) operation, which restarts only the node that receives it, or a process or container restart. [`restart_service`](../operations-api/operations.md#restart_service) restarts only worker threads, which keep the process's flags, so it does not apply a change, even with `"replicated": true`. To roll back, remove the setting from wherever it was set (the config file, `HARPER_SET_CONFIG`, `HARPER_CONFIG` or the `THREADS_V8FLAGS` environment variable) and restart the process. +- **When it takes effect.** Flags are read once per process. A changed value takes effect when the whole process restarts: the [`restart`](../operations-api/operations.md#restart) operation, which restarts only the node that receives it, or a process or container restart. [`restart_service`](../operations-api/operations.md#restart_service) restarts only worker threads, which keep the process's flags, so it does not apply a change, even with `"replicated": true`. To roll back, remove the setting from `HARPER_SET_CONFIG` or `HARPER_CONFIG` if it came from there, and from `harper-config.yaml` (for example `set_configuration` with `"threads_v8Flags": null`), then restart the process. A `THREADS_V8FLAGS` environment variable is written into `harper-config.yaml` at startup, so unsetting the variable alone leaves the flags in place. - **Expert setting.** Flags change V8's behavior for the whole process and are not validated beyond the `--` prefix. A conflicting combination can stop the process at startup. Measure memory and throughput with your workload before relying on a flag in production. --- From 89acc61492c2a337f286b917aba90951500610b2 Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sat, 10 Oct 2026 09:39:38 -0600 Subject: [PATCH 7/7] Say to unset THREADS_V8FLAGS too when rolling back Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VKZAtTiprHW8Sp1Ff4hGAZ Dispatch-Task: harper-threads-v8flags --- reference/configuration/options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/configuration/options.md b/reference/configuration/options.md index accc09ea..d1212841 100644 --- a/reference/configuration/options.md +++ b/reference/configuration/options.md @@ -121,7 +121,7 @@ The value can also be set from the environment, for example `HARPER_SET_CONFIG=' - **Validation.** Surrounding whitespace is trimmed, and an empty entry is ignored. An entry that does not start with `--` is refused by `set_configuration`, and stops Harper at startup with an error naming `threads.v8Flags`. V8 skips a flag it does not recognize and only prints `Error: unrecognized flag` to standard error, so check the spelling against your Node version (`node --v8-options`). - **Implied flags are not applied.** On the command line, some flags turn on others; `--optimize-for-size` also caps the young-generation semi-space at 1 MB. Applied at runtime, a flag does not do that, so list the implied flags explicitly, as the example does with `--max-semi-space-size=1`. -- **When it takes effect.** Flags are read once per process. A changed value takes effect when the whole process restarts: the [`restart`](../operations-api/operations.md#restart) operation, which restarts only the node that receives it, or a process or container restart. [`restart_service`](../operations-api/operations.md#restart_service) restarts only worker threads, which keep the process's flags, so it does not apply a change, even with `"replicated": true`. To roll back, remove the setting from `HARPER_SET_CONFIG` or `HARPER_CONFIG` if it came from there, and from `harper-config.yaml` (for example `set_configuration` with `"threads_v8Flags": null`), then restart the process. A `THREADS_V8FLAGS` environment variable is written into `harper-config.yaml` at startup, so unsetting the variable alone leaves the flags in place. +- **When it takes effect.** Flags are read once per process. A changed value takes effect when the whole process restarts: the [`restart`](../operations-api/operations.md#restart) operation, which restarts only the node that receives it, or a process or container restart. [`restart_service`](../operations-api/operations.md#restart_service) restarts only worker threads, which keep the process's flags, so it does not apply a change, even with `"replicated": true`. To roll back, remove the setting from `HARPER_SET_CONFIG` or `HARPER_CONFIG` if it came from there, and from `harper-config.yaml` (for example `set_configuration` with `"threads_v8Flags": null`), then restart the process. A `THREADS_V8FLAGS` environment variable is written into `harper-config.yaml` at every startup, so unset it as well; unsetting the variable alone leaves the flags in the file. - **Expert setting.** Flags change V8's behavior for the whole process and are not validated beyond the `--` prefix. A conflicting combination can stop the process at startup. Measure memory and throughput with your workload before relying on a flag in production. ---