Skip to content

docs: Node Renderer container deployment guide#2675

Closed
jay-shaka wants to merge 23 commits intomainfrom
docs/node-renderer-container-operations
Closed

docs: Node Renderer container deployment guide#2675
jay-shaka wants to merge 23 commits intomainfrom
docs/node-renderer-container-operations

Conversation

@jay-shaka
Copy link
Copy Markdown

@jay-shaka jay-shaka commented Mar 18, 2026

What

Adds a comprehensive guide for deploying the Node Renderer in containerized environments (Docker, Kubernetes, ControlPlane, etc.).

Why

This addresses the operational knowledge gap about frequent OOM restarts, memory growth in the Node Renderer, and the sidecar vs separate workload tradeoff.

What's Covered

  1. Architecture options — Sidecar containers (recommended) vs. separate workloads
  2. Host binding0.0.0.0 requirement for container environments
  3. Performance optimizationNODE_OPTIONS --max-old-space-size, worker count tuning, rolling restarts, jemalloc for Rails
  4. Container resource allocation — Starting-point CPU/memory recommendations
  5. Autoscaling considerations — How sidecar metrics aggregation affects scaling thresholds
  6. Error trackingERR_STREAM_PREMATURE_CLOSE startup errors, OOM exit codes, health checks
  7. Troubleshooting — OOM diagnosis, connection refused, version drift, latency, startup race conditions
  8. ControlPlane-specific notes

Cross-references added

  • docs/oss/building-features/node-renderer/basics.md — link in References
  • docs/README.md — link in Pro docs section

CC: @justin808 @sergey-alekseev @AbanoubGhadworban

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive Node Renderer: Container Deployment guide covering deployment architectures, networking/security notes, memory and performance tuning, autoscaling considerations, health checks, error handling, and operational troubleshooting.
    • Added new “Pro features” links: Code Splitting, Ruby API (Pro), Upgrading Pro, Troubleshooting, and Node Renderer: Container Deployment.
    • Linked the Container Deployment guide from the Node Renderer basics references.

Covers sidecar vs. separate workload architecture, host binding,
memory management (NODE_OPTIONS --max-old-space-size), worker count
tuning, rolling restarts, autoscaling with sidecars, error tracking
(ERR_STREAM_PREMATURE_CLOSE, OOM), health checks, and
ControlPlane-specific notes.

Cross-references added to basics.md and docs/README.md.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Added a new Node Renderer container deployment guide and updated documentation links; content documents deployment architectures, host binding, memory and performance tuning, autoscaling considerations, startup/error handling, observability, and troubleshooting.

Changes

Cohort / File(s) Summary
Docs index & references
docs/README.md, docs/oss/building-features/node-renderer/basics.md
Inserted links to the new container deployment guide under the "Pro features" list and the Node Renderer "References" section.
Node Renderer container deployment guide
docs/oss/building-features/node-renderer/container-deployment.md
Added a new, detailed guide describing three deployment architectures (single container, sidecar, separate workloads), host binding behavior (localhost vs 0.0.0.0), security notes, memory/V8 tuning (NODE_OPTIONS), worker sizing and restart strategies, Kubernetes resource suggestions, autoscaling implications, startup race/error detection (ERR_STREAM_PREMATURE_CLOSE, exit codes), observability/error reporting locations, troubleshooting scenarios, and ControlPlane notes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

I'm a rabbit in the docs with a nimble hop,
I leave a guide where container tips don't stop.
Sidecars, heaps, and worker counts to chart,
Logs and probes to keep the system smart,
🐇 Deploy with care — a tiny, happy hop!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'docs: Node Renderer container deployment guide' directly and clearly summarizes the main change—adding comprehensive documentation for deploying the Node Renderer in containerized environments.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/node-renderer-container-operations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 18, 2026

Greptile Summary

This PR adds a new container-deployment.md guide for deploying the Node Renderer in containerized environments, plus navigation links in docs/README.md and basics.md. The guide covers architecture options (sidecar vs. separate workloads), host binding, memory/worker tuning, autoscaling, error tracking, and troubleshooting — filling a real operational knowledge gap.

Key points:

  • P1 logic error: The "Host Binding" section (line 70) incorrectly states that both sidecar and separate-workload configurations require 0.0.0.0 binding. For Kubernetes pods, sidecar containers share a network namespace and the default localhost binding works correctly. This contradicts the advantages listed for sidecars ("Rails connects to the renderer via localhost") and the Troubleshooting section (line 268) which correctly acknowledges localhost as the default for sidecars. The section needs to distinguish between Kubernetes pods (where localhost works for sidecars) and Docker Compose or separate workloads (where 0.0.0.0 is needed).
  • Worker count formula: The /2 divisor in the sizing formula is unexplained. Since each worker handles one synchronous SSR request at a time, the rationale for halving the result should be documented so operators can calibrate it correctly for their workload.
  • Minor: The ASCII pod diagram has a visual break in the outer boundary at the localhost junction ( should be ).

Confidence Score: 3/5

  • Documentation-only PR, safe to merge but contains a technically incorrect claim about host binding for sidecar containers that should be corrected before publishing.
  • The guide is well-structured and covers the topic thoroughly, but the host binding section contains incorrect guidance for Kubernetes sidecar deployments — claiming 0.0.0.0 is required when localhost is correct and sufficient. This is the canonical use case promoted throughout the document and the error could cause unnecessary security exposure or configuration confusion. The worker sizing formula also has an unexplained factor. No code is changed, so no runtime regressions are possible.
  • docs/oss/building-features/node-renderer/container-deployment.md — host binding section (line 70) and worker count formula (line 134) need review.

Important Files Changed

Filename Overview
docs/oss/building-features/node-renderer/container-deployment.md New comprehensive container deployment guide. Contains a P1 logic error: claims both sidecar and separate-workload configurations require 0.0.0.0 binding, which is incorrect for Kubernetes pods where sidecars share a network namespace. Also has an unexplained /2 factor in the worker count formula and a minor ASCII art visual issue.
docs/oss/building-features/node-renderer/basics.md Adds a single reference link to the new container-deployment.md guide. Change is minimal and correct.
docs/README.md Adds a navigation entry for the new container deployment guide in the Pro docs section, correctly placed between the Node Renderer Basics and Code Splitting entries.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Rails Container] -->|HTTP via localhost:3800| B[Node Renderer Container]
    B -->|SSR Response| A

    subgraph Sidecar Pod
        A
        B
    end

    subgraph "Separate Workload"
        C[Rails Workload] -->|HTTP via service DNS| D[Node Renderer Workload]
        D -->|SSR Response| C
    end

    subgraph "Node Renderer Internals"
        E[Master Process] -->|fork| F[Worker 1]
        E -->|fork| G[Worker 2]
        E -->|fork| H[Worker N]
        F -->|allWorkersRestartInterval| E
    end

    I[OOM / Container Restart] -->|Exit 137| J[cgroup OOM Kill]
    I -->|Exit 1| K[App Crash - check logs]
Loading

Last reviewed commit: "docs: add Node Rende..."

Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e33d72bb49

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 18, 2026

Review: Node Renderer Container Deployment Guide

Good addition — this fills a real operational gap for teams running Node Renderer in containerized environments. The structure is clear and the troubleshooting section is practical. A few issues to address before merging:

Must-fix

  1. ASCII diagram broken (line 27) — bottom border has two corners. Inline suggestion posted.

  2. Host binding claim inaccurate for Kubernetes sidecars (line 70) — The guide states that 0.0.0.0 is required "in both sidecar and separate-workload configurations," but this is incorrect for Kubernetes. Containers within the same pod share a network namespace, so localhost binding works fine and is preferable from a security standpoint (avoids exposing the renderer on all interfaces). The 0.0.0.0 requirement only applies to separate workloads and Docker Compose setups without shared networking. Inline suggestion posted.

  3. jemalloc LD_PRELOAD path is x86_64-only (line 177) — The hardcoded path /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 silently fails on ARM containers (Graviton, Apple Silicon builds). Many production Kubernetes clusters now run ARM nodes. Inline suggestion posted.

Suggestions

  • Worker formula /2 is unexplained (lines 135–141) — Readers will copy the formula but won't understand why dividing by 2 is correct. A sentence explaining the assumption (e.g., rendering is faster than a full request cycle, so each worker can handle N concurrent Rails threads) would help.

  • Rolling restart config units not explicit (lines 151–155) — allWorkersRestartInterval and delayBetweenIndividualWorkerRestarts are in minutes; gracefulWorkerRestartTimeout is in seconds. The current comments say "6 hours" / "2 minutes" / "30 seconds" which is correct, but doesn't make the unit of the numeric value obvious. Inline suggestion posted.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
docs/oss/building-features/node-renderer/container-deployment.md (5)

85-87: Add language identifier to the environment variable code block.

The fenced code block should specify bash or shell as the language identifier.

📝 Proposed fix
-```
+```bash
 RENDERER_HOST=0.0.0.0
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/oss/building-features/node-renderer/container-deployment.md around
lines 85 - 87, The fenced code block containing the environment variable
RENDERER_HOST=0.0.0.0 is missing a language identifier; update the
triple-backtick fence to include a shell language (e.g., bash or shell) so
the block becomes a bash/shell code fence to enable proper syntax highlighting
for RENDERER_HOST.


</details>

---

`133-135`: **Add language identifier to the formula code block.**

Specify `text` or `plaintext` as the language identifier.



<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 renderer_workers ≥ (WEB_CONCURRENCY × RAILS_MAX_THREADS × ssr_request_ratio) / 2
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/oss/building-features/node-renderer/container-deployment.md around
lines 133 - 135, The fenced code block containing the formula "renderer_workers
≥ (WEB_CONCURRENCY × RAILS_MAX_THREADS × ssr_request_ratio) / 2" is missing a
language identifier; update the block fence to include a language tag such as
"text" or "plaintext" (e.g., text) so the snippet is properly annotated in the Markdown; locate the exact fenced block with that formula and add the language identifier to the opening fence.


</details>

---

`16-28`: **Add language identifier to the diagram code block.**

The fenced code block containing the ASCII diagram should specify a language identifier (e.g., `text` or `plaintext`) to comply with Markdown best practices.



<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 ┌─────────────────────────────────┐
 │           Pod / Workload        │
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/oss/building-features/node-renderer/container-deployment.md around
lines 16 - 28, The fenced ASCII diagram block lacks a language identifier;
update the opening fence for that diagram (the triple-backtick before the ASCII
pod/workload diagram) to include a language token such as text or plaintext
(e.g., ```text) so the code block is properly identified and rendered.


</details>

---

`106-108`: **Add language identifier to the code block.**

Specify `bash` or `shell` as the language identifier for the environment variable example.



<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```bash
 NODE_OPTIONS="--max-old-space-size=512"
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/oss/building-features/node-renderer/container-deployment.md around
lines 106 - 108, The code block showing the environment variable NODE_OPTIONS
should include a language identifier so it renders as shell/bash; update the
fenced code block from tobash (or shell) so the example `NODE_OPTIONS="--max-old-space-size=512"` is marked as bash/shell—for instance change the fence around the NODE_OPTIONS line in the container deployment markdown to use bash.


</details>

---

`140-142`: **Add language identifier to the example calculation.**

Specify `text` or `plaintext` as the language identifier.



<details>
<summary>📝 Proposed fix</summary>

```diff
-```
+```text
 renderer_workers ≥ (4 × 8 × 0.5) / 2 = 8 workers
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/oss/building-features/node-renderer/container-deployment.md around
lines 140 - 142, Update the code block containing "renderer_workers ≥ (4 × 8 ×
0.5) / 2 = 8 workers" to include a language identifier (e.g., text or plaintext)
on the opening triple-backtick so the block becomes text (or plaintext)
followed by the same line; this ensures the example calculation renders with the
specified language highlighting in the documentation.


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Inline comments:
In @docs/oss/building-features/node-renderer/container-deployment.md:

  • Around line 304-312: The file ends without a trailing newline after the final
    "## References" section; open the file
    docs/oss/building-features/node-renderer/container-deployment.md (look for the
    "## References" heading and the listed links) and add a single newline character
    at the end of the file so it terminates with a newline character (ensure the
    file ends with '\n').
  • Line 70: The current sentence "By default, the Node Renderer binds to
    localhost, which rejects connections from other containers. In both sidecar
    and separate-workload configurations, you need to bind to 0.0.0.0:" is
    incorrect and conflicts with the later note that sidecars can use localhost;
    update that sentence to clarify that when the Node Renderer runs as a true
    sidecar (shared pod network namespace) binding to localhost is acceptable, but
    when running as a separate workload or in Docker Compose (separate network
    namespaces) you must bind to 0.0.0.0; reference the exact phrasing "By
    default, the Node Renderer binds to localhost..." to locate and replace the
    text and add a short note about Kubernetes pod network namespace sharing to
    justify the distinction.

Nitpick comments:
In @docs/oss/building-features/node-renderer/container-deployment.md:

  • Around line 85-87: The fenced code block containing the environment variable
    RENDERER_HOST=0.0.0.0 is missing a language identifier; update the
    triple-backtick fence to include a shell language (e.g., bash or shell) so
    the block becomes a bash/shell code fence to enable proper syntax highlighting
    for RENDERER_HOST.
  • Around line 133-135: The fenced code block containing the formula
    "renderer_workers ≥ (WEB_CONCURRENCY × RAILS_MAX_THREADS × ssr_request_ratio) /
    2" is missing a language identifier; update the block fence to include a
    language tag such as "text" or "plaintext" (e.g., text) so the snippet is properly annotated in the Markdown; locate the exact fenced block with that formula and add the language identifier to the opening fence.
  • Around line 16-28: The fenced ASCII diagram block lacks a language identifier;
    update the opening fence for that diagram (the triple-backtick before the ASCII
    pod/workload diagram) to include a language token such as text or plaintext
    (e.g., ```text) so the code block is properly identified and rendered.
  • Around line 106-108: The code block showing the environment variable
    NODE_OPTIONS should include a language identifier so it renders as shell/bash;
    update the fenced code block from tobash (or shell) so the example `NODE_OPTIONS="--max-old-space-size=512"` is marked as bash/shell—for instance change the fence around the NODE_OPTIONS line in the container deployment markdown to use bash.
  • Around line 140-142: Update the code block containing "renderer_workers ≥ (4 ×
    8 × 0.5) / 2 = 8 workers" to include a language identifier (e.g., text or
    plaintext) on the opening triple-backtick so the block becomes ```text (or
renders with the specified language highlighting in the documentation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 839ec7b6-9439-4854-990a-0816307180ca

📥 Commits

Reviewing files that changed from the base of the PR and between 3cf2881 and e33d72b.

📒 Files selected for processing (3)
  • docs/README.md
  • docs/oss/building-features/node-renderer/basics.md
  • docs/oss/building-features/node-renderer/container-deployment.md

Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
…step

Per feedback from Sergey: single container is the simplest and
should be the default. Sidecar is the next step when you need to
isolate Rails vs Node memory issues. Separate workloads is overkill
for most setups.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
docs/oss/building-features/node-renderer/container-deployment.md (1)

107-107: ⚠️ Potential issue | 🟡 Minor

Clarify sidecar vs separate-workload host binding requirements.

Line 107 conflicts with Lines 305–306. A true sidecar (same pod network namespace) can use localhost; 0.0.0.0 is required for separate workloads (and often Docker Compose-style separate namespaces).

✏️ Proposed clarification
-By default, the Node Renderer binds to `localhost`, which rejects connections from other containers. In both sidecar and separate-workload configurations, you need to bind to `0.0.0.0`:
+By default, the Node Renderer binds to `localhost`. For **separate workloads**, bind to `0.0.0.0` so other containers can connect. For **true sidecars** in Kubernetes (same pod network namespace), `localhost` works; `0.0.0.0` is also safe when needed by your runtime/network setup:

Also applies to: 305-306

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/oss/building-features/node-renderer/container-deployment.md` at line
107, Update the paragraph that currently states "By default, the Node Renderer
binds to `localhost`, which rejects connections from other containers. In both
sidecar and separate-workload configurations, you need to bind to `0.0.0.0`:" to
clarify the difference between true sidecar and separate-workload deployments:
explain that a true sidecar (same pod/network namespace) can bind to `localhost`
and still accept requests from the other container in the same namespace,
whereas separate workloads or multi-container setups that use distinct network
namespaces (including Docker Compose-style setups) must bind to `0.0.0.0` to
accept external container connections; also update the duplicate guidance around
the later paragraph that references binding behavior to match this distinction
so both places are consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/oss/building-features/node-renderer/container-deployment.md`:
- Around line 16-25: Several fenced code blocks lack language annotations
causing markdownlint MD040; update each fence containing the ASCII diagrams to
use ```text, the environment variable lines (RENDERER_HOST and NODE_OPTIONS) to
use ```bash, and the formula/worker lines to use ```text so all fences are
explicitly annotated (look for the ASCII container/pod diagrams, the
RENDERER_HOST and NODE_OPTIONS blocks, and the "renderer_workers ≥ ..." and its
calculated-example block and add the appropriate language tag to each opening
```).

---

Duplicate comments:
In `@docs/oss/building-features/node-renderer/container-deployment.md`:
- Line 107: Update the paragraph that currently states "By default, the Node
Renderer binds to `localhost`, which rejects connections from other containers.
In both sidecar and separate-workload configurations, you need to bind to
`0.0.0.0`:" to clarify the difference between true sidecar and separate-workload
deployments: explain that a true sidecar (same pod/network namespace) can bind
to `localhost` and still accept requests from the other container in the same
namespace, whereas separate workloads or multi-container setups that use
distinct network namespaces (including Docker Compose-style setups) must bind to
`0.0.0.0` to accept external container connections; also update the duplicate
guidance around the later paragraph that references binding behavior to match
this distinction so both places are consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d978da0b-c8be-4d70-8c59-b162d2abceef

📥 Commits

Reviewing files that changed from the base of the PR and between e33d72b and d48887f.

📒 Files selected for processing (1)
  • docs/oss/building-features/node-renderer/container-deployment.md

Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d48887fee3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
Comment thread docs/oss/building-features/node-renderer/container-deployment.md
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 18, 2026

Review: Node Renderer Container Deployment Guide

Good addition - this fills a real operational gap. Structure is clear, troubleshooting section is practical, and the architecture progression (single to sidecar to separate) is well motivated. A few issues to fix before merging:

Must-fix:

  1. Host binding section is incorrect for Kubernetes sidecars (line 107). The guide claims 0.0.0.0 is required in both sidecar and separate-workload configurations, but this is wrong for Kubernetes pods. Containers in the same pod share a network namespace and the loopback interface, so Rails can reach a localhost-bound renderer without any binding change. 0.0.0.0 is only needed for (a) separate workloads (different pods) and (b) Kubernetes HTTP health probes, which the kubelet initiates from outside the pod network namespace. The current wording conflicts with the sidecar advantages (Rails still connects via localhost) and the troubleshooting section (line 305). Inline suggestion posted.

  2. jemalloc LD_PRELOAD path is x86_64-only (line 214). The hardcoded path /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 silently does nothing on ARM64 containers (AWS Graviton, arm64 CI runners). Many production Kubernetes clusters now run mixed or arm64 node pools. At minimum add a comment noting the arm64 path (/usr/lib/aarch64-linux-gnu/libjemalloc.so.2). Inline suggestion posted.

  3. Broken ASCII border on sidecar diagram (line 59). The bottom boundary has two closing-corner characters where the first should be a T-junction to connect the localhost line. Inline suggestion posted.

Suggestions:

  1. Worker formula /2 divisor is unexplained (lines 169-178). The implicit assumption is that each SSR render takes roughly half the time of a full Rails request, so one worker serves ~2 Rails threads. Without that sentence, operators will either copy the formula blindly or distrust it. Inline suggestion with proposed wording posted.

  2. Rolling restart config units are implicit (lines 188-191). allWorkersRestartInterval and delayBetweenIndividualWorkerRestarts are in minutes; gracefulWorkerRestartTimeout is in seconds. The English comments are correct but the unit is not visible on the number itself. Inline suggestion adds explicit unit labels.

Verified:

  • All linked files exist (js-configuration.md, error-reporting-and-tracing.md, heroku.md, js-memory-leaks.md, profiling-server-side-rendering-code.md, troubleshooting.md).
  • The custom-fastify-configuration anchor referenced in the startup errors section exists in js-configuration.md.
  • js-configuration.md confirms units: allWorkersRestartInterval = minutes, delayBetweenIndividualWorkerRestarts = minutes, gracefulWorkerRestartTimeout = seconds, consistent with the comments in the example.

justin808 added a commit that referenced this pull request Mar 26, 2026
## Summary

- replace dead `https://pro.reactonrails.com` links with the live
canonical Pro docs landing page at `https://reactonrails.com/docs/pro/`
- update the one user-facing runtime warning in `ReactOnRails::Utils` to
stop sending users to the failing subdomain
- keep the scope limited to non-overlapping files outside the active
docs PRs

## Scope notes

- Supports shakacode/reactonrails.com#59
- Intentionally does not touch
`react_on_rails/lib/generators/react_on_rails/pro_setup.rb`, which is
already tracked by #2575
- Intentionally does not touch the stale `/pro` page content /
`docs/pro/react-on-rails-pro.md`, which is tracked by #2838
- Intentionally excludes files already being modified in active PRs:
#2610, #2651, #2675, #2831, and #2850

## Validation

Passed:
- `bundle exec rubocop react_on_rails/lib/react_on_rails/utils.rb`
- `git diff --check`
- `git diff --name-only origin/main...HEAD | rg '\.md$' | xargs pnpm dlx
[email protected] --check`
- custom local relative-link scan across the changed markdown files
- `curl -I -L` checks showing:
  - `https://reactonrails.com/docs/pro/` -> `200`
  - `https://pro.reactonrails.com` -> `500`

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are documentation link updates plus a single
user-facing warning string, with no behavioral impact beyond directing
users to a new URL.
> 
> **Overview**
> Updates documentation to replace references to the dead
`https://pro.reactonrails.com` site with the canonical Pro landing page
at `https://reactonrails.com/docs/pro/` across the README and multiple
OSS docs.
> 
> Also updates the
`ReactOnRails::Utils.immediate_hydration_pro_install_warning` message to
point users at the new Pro docs URL when `immediate_hydration: true` is
used without the Pro gem.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
457f7d5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated React on Rails Pro documentation links across the README, API
references, feature guides, configuration documentation, migration
guides, release notes, and installation messages to consistently direct
users to the new centralized Pro documentation hub for improved
navigation and accessibility.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
justin808 added a commit that referenced this pull request Mar 26, 2026
## Summary

This docs cleanup pass aligns repo docs and user-facing help output with
the current published docs structure.

Changes in this PR:
- replace stale docs-route references in runtime/help output with the
current docs paths
- replace legacy Pro wiki links and stale external references in OSS
docs
- document current `ReactOnRails.render` return behavior for React 18+
vs React 16/17
- update internal contributor guidance to point at the canonical Pro
docs home

## Scope notes

- Closes #2839
- Partial #2838
- Intentionally excludes files already being modified in active docs
PRs: #2610, #2651, #2675, and #2831

## Validation

Passed:
- `bundle exec rubocop
react_on_rails/lib/react_on_rails/configuration.rb
react_on_rails/lib/react_on_rails/doctor.rb
react_on_rails/lib/react_on_rails/packer_utils.rb
react_on_rails/lib/react_on_rails/packs_generator.rb
react_on_rails/lib/react_on_rails/server_rendering_js_code.rb
react_on_rails/lib/tasks/generate_packs.rake
react_on_rails/spec/dummy/spec/packs_generator_spec.rb`
- `git diff --name-only origin/main...HEAD | rg '\.md$' | xargs pnpm dlx
[email protected] --check`
- `git diff --check`
- custom local relative-link scan across the changed markdown files
- `curl -I -L` checks for `https://invite.reactrails.com`,
`https://jsdoc.app/`, and `https://reactonrails.com/docs/pro/`

Not run:
- `bundle exec rspec
react_on_rails/spec/dummy/spec/packs_generator_spec.rb`
- blocked in this clean worktree because the dummy-app spec loads
`rails_helper` from the dummy app environment and that bundle/setup is
not present here

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are limited to documentation text and user-facing
help/error message URLs, with no behavioral code changes.
> 
> **Overview**
> Updates docs and in-tool messaging to match the reorganized
`reactonrails.com` documentation structure, replacing legacy wiki/old
guide URLs across OSS guides, Pro references, and generator docs.
> 
> Clarifies the `ReactOnRails.render` API docs to reflect React 18+ root
return behavior vs React 16/17, and adds guidance warning that repeated
calls on the same DOM node are not deduplicated.
> 
> Refreshes community/support links (Slack invite, JSDoc) and updates
several runtime error/help messages and corresponding specs to point at
the new canonical doc routes.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
296ecc1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Updated many guide links to the reorganized documentation site
(including Pro docs and upgrade/migration paths).
* Clarified API docs for render behavior across React versions and added
guidance about repeated renders.
* Replaced community Slack invite/link and updated external JSDoc
reference.
* Adjusted error/help message and test links to point to the correct
docs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 27, 2026

PR Review: Node Renderer Container Deployment Guide

This is a high-quality, operationally useful documentation addition. The three-option architecture comparison, worker sizing formula, and OOM diagnosis workflow are genuinely valuable. All internal links verified as valid.

Issues requiring fixes before merge

1. Named import should be default import (copy-paste impact)

Line 111 uses { reactOnRailsProNodeRenderer } (named import), but every other doc in this directory and the package itself uses a default import. Users will copy-paste this and get a silent runtime failure.

2. Sidecar host binding is technically incorrect

The guide states that both sidecar and separate-workload configurations need 0.0.0.0 binding. This is wrong for sidecars: containers in the same Kubernetes pod share a network namespace and communicate over localhost0.0.0.0 is not required. The guide then contradicts itself in the Troubleshooting section (line 305) which correctly says sidecars can use localhost. Only separate-workload configurations truly need 0.0.0.0.

Minor issues worth addressing

  • Mixed units in config block (lines 189-192): allWorkersRestartInterval is in minutes, gracefulWorkerRestartTimeout is in seconds — the code block does not call this out, which could confuse users who assume the same unit.
  • Broken ASCII diagram (line 59): The sidecar diagram's bottom border has a stray in the middle of the line.
  • Memory estimates need context (lines 135-137): The 500-600 MB figure is stated without specifying worker count or Node version, which could lead to incorrect resource planning.
  • README section organization: The 5 new links are appended without subgrouping, mixing operational, reference, upgrade, and troubleshooting docs into an unstructured list.

Comment thread docs/oss/building-features/node-renderer/container-deployment.md
Comment thread docs/oss/building-features/node-renderer/container-deployment.md Outdated
justin808 and others added 4 commits March 28, 2026 08:28
## Summary

- Adds `.claude/docs/docs-competitive-landscape.md` with React on Rails
competitor analysis (Inertia Rails, Vite Ruby, react-rails, Hotwire) and
documentation improvement targets
- Adds `.claude/docs/docs-templates.md` with RoR-specific template
examples (README Hello World with `react_component`, API reference,
config reference, troubleshooting)
- Updates `CLAUDE.md` to reference both new docs files

This is the react_on_rails side of moving project-specific content out
of the shared `claude-code-commands-skills-agents` repo.

Addresses
shakacode/claude-code-commands-skills-agents#19
Addresses
shakacode/claude-code-commands-skills-agents#20

## Test plan

- [x] Files contain only React on Rails-specific content (no Shakapacker
sections)
- [x] CLAUDE.md references both new files
- [x] Pre-commit hooks pass (prettier, trailing newlines)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: documentation-only additions plus a reference update in
`CLAUDE.md`, with no runtime or build changes.
> 
> **Overview**
> Adds two new Claude guidance docs: a **competitive documentation
landscape** (`.claude/docs/docs-competitive-landscape.md`) summarizing
key competitors and doc gaps to target, and **project-specific
documentation templates** (`.claude/docs/docs-templates.md`) with
canonical React on Rails examples for README/API/config/troubleshooting
sections.
> 
> Updates `CLAUDE.md` to include these new docs in the recommended
reading list.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2848581. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated internal documentation framework with enhanced guidance
covering implementation patterns, configuration references, and
troubleshooting examples for React on Rails projects.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
…irectory (#2846)

Bumps the npm-security group with 1 update in the / directory:
[fastify](https://github.com/fastify/fastify).

Updates `fastify` from 5.8.1 to 5.8.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/fastify/fastify/releases">fastify's
releases</a>.</em></p>
<blockquote>
<h2>v5.8.3</h2>
<h2>⚠️ Security Release</h2>
<p>This fixes CVE CVE-2026-3635 <a
href="https://github.com/fastify/fastify/security/advisories/GHSA-444r-cwp2-x5xf">https://github.com/fastify/fastify/security/advisories/GHSA-444r-cwp2-x5xf</a>.</p>
<h2>What's Changed</h2>
<ul>
<li>docs(readme): add <a
href="https://github.com/Tony133"><code>@​Tony133</code></a> to plugin
team by <a href="https://github.com/Tony133"><code>@​Tony133</code></a>
in <a
href="https://redirect.github.com/fastify/fastify/pull/6565">fastify/fastify#6565</a></li>
<li>Updated Plugins-Guide.md; Changed &quot;fastify&quot; to
&quot;instance&quot; during plugin registration to showcase that it's
added as a child by <a
href="https://github.com/kyrylchenko"><code>@​kyrylchenko</code></a> in
<a
href="https://redirect.github.com/fastify/fastify/pull/6566">fastify/fastify#6566</a></li>
<li>test: use fastify.test in test case by <a
href="https://github.com/climba03003"><code>@​climba03003</code></a> in
<a
href="https://redirect.github.com/fastify/fastify/pull/6568">fastify/fastify#6568</a></li>
<li>docs: use fastify.example in documentation by <a
href="https://github.com/climba03003"><code>@​climba03003</code></a> in
<a
href="https://redirect.github.com/fastify/fastify/pull/6567">fastify/fastify#6567</a></li>
<li>docs: add common performance degradation guidance by <a
href="https://github.com/maxpetrusenko"><code>@​maxpetrusenko</code></a>
in <a
href="https://redirect.github.com/fastify/fastify/pull/6520">fastify/fastify#6520</a></li>
<li>docs(server): fix camelCase anchor links in TOC by <a
href="https://github.com/Deepvamja"><code>@​Deepvamja</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6530">fastify/fastify#6530</a></li>
<li>ci(link-checker): fix root-relative links resolution by <a
href="https://github.com/barba-rossa"><code>@​barba-rossa</code></a> in
<a
href="https://redirect.github.com/fastify/fastify/pull/6535">fastify/fastify#6535</a></li>
<li>docs: update syntax markdown, absolute paths and links by <a
href="https://github.com/Tony133"><code>@​Tony133</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6569">fastify/fastify#6569</a></li>
<li>docs: clarify content-type parser/schema mismatch is outside threat
model by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6537">fastify/fastify#6537</a></li>
<li>docs: fix incorrect code examples in Reply and Request reference by
<a
href="https://github.com/mahmoodhamdi"><code>@​mahmoodhamdi</code></a>
in <a
href="https://redirect.github.com/fastify/fastify/pull/6582">fastify/fastify#6582</a></li>
<li>docs: replace redirected npm.im http-errors link by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6588">fastify/fastify#6588</a></li>
<li>types: Allow port to be null in request type definition by <a
href="https://github.com/TristanBarlow"><code>@​TristanBarlow</code></a>
in <a
href="https://redirect.github.com/fastify/fastify/pull/6589">fastify/fastify#6589</a></li>
<li>docs: update links by <a
href="https://github.com/Tony133"><code>@​Tony133</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6593">fastify/fastify#6593</a></li>
<li>ci(lock-threads): use shared lock-threads workflow by <a
href="https://github.com/Fdawgs"><code>@​Fdawgs</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6592">fastify/fastify#6592</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/kyrylchenko"><code>@​kyrylchenko</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6566">fastify/fastify#6566</a></li>
<li><a
href="https://github.com/maxpetrusenko"><code>@​maxpetrusenko</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6520">fastify/fastify#6520</a></li>
<li><a href="https://github.com/Deepvamja"><code>@​Deepvamja</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6530">fastify/fastify#6530</a></li>
<li><a
href="https://github.com/barba-rossa"><code>@​barba-rossa</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6535">fastify/fastify#6535</a></li>
<li><a
href="https://github.com/mahmoodhamdi"><code>@​mahmoodhamdi</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6582">fastify/fastify#6582</a></li>
<li><a
href="https://github.com/TristanBarlow"><code>@​TristanBarlow</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6589">fastify/fastify#6589</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/fastify/fastify/compare/v5.8.2...v5.8.3">https://github.com/fastify/fastify/compare/v5.8.2...v5.8.3</a></p>
<h2>v5.8.2</h2>
<h2>What's Changed</h2>
<ul>
<li>docs(ecosystem): add <code>@​yeliex/fastify-problem-details</code>
by <a href="https://github.com/yeliex"><code>@​yeliex</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6546">fastify/fastify#6546</a></li>
<li>Revert &quot;chore: upgrade borp to v1.0.0&quot; by <a
href="https://github.com/climba03003"><code>@​climba03003</code></a> in
<a
href="https://redirect.github.com/fastify/fastify/pull/6564">fastify/fastify#6564</a></li>
<li>docs: document body validation with custom content type parsers by
<a href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6556">fastify/fastify#6556</a></li>
<li>docs(ecosystem): add fastify-file-router by <a
href="https://github.com/bhouston"><code>@​bhouston</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6441">fastify/fastify#6441</a></li>
<li>docs: add fastify-svelte-view to Ecosystem list by <a
href="https://github.com/matths"><code>@​matths</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6453">fastify/fastify#6453</a></li>
<li>fix: anchor keyValuePairsReg to prevent quadratic backtracking by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6558">fastify/fastify#6558</a></li>
<li>docs: added note on handling of invalid URLs in setNotFoundHandler
by <a
href="https://github.com/leftieFriele"><code>@​leftieFriele</code></a>
in <a
href="https://redirect.github.com/fastify/fastify/pull/5661">fastify/fastify#5661</a></li>
<li>docs(guides): update codemod links by <a
href="https://github.com/OluchiEzeifedikwa"><code>@​OluchiEzeifedikwa</code></a>
in <a
href="https://redirect.github.com/fastify/fastify/pull/6479">fastify/fastify#6479</a></li>
<li>docs: add <code>@​glidemq/fastify</code> to community plugins by <a
href="https://github.com/avifenesh"><code>@​avifenesh</code></a> in <a
href="https://redirect.github.com/fastify/fastify/pull/6560">fastify/fastify#6560</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/yeliex"><code>@​yeliex</code></a> made
their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6546">fastify/fastify#6546</a></li>
<li><a href="https://github.com/matths"><code>@​matths</code></a> made
their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6453">fastify/fastify#6453</a></li>
<li><a
href="https://github.com/leftieFriele"><code>@​leftieFriele</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/5661">fastify/fastify#5661</a></li>
<li><a
href="https://github.com/OluchiEzeifedikwa"><code>@​OluchiEzeifedikwa</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6479">fastify/fastify#6479</a></li>
<li><a href="https://github.com/avifenesh"><code>@​avifenesh</code></a>
made their first contribution in <a
href="https://redirect.github.com/fastify/fastify/pull/6560">fastify/fastify#6560</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/fastify/fastify/commit/a3e77ce171516e95f0c28ce60b9e5228a4c42fe4"><code>a3e77ce</code></a>
Bumped v5.8.3</li>
<li><a
href="https://github.com/fastify/fastify/commit/4e1db5bd0012ccf63a49ff105a63e25981b9a747"><code>4e1db5b</code></a>
fix: gate host and protocol getters on proxy trust function</li>
<li><a
href="https://github.com/fastify/fastify/commit/a22217f9420f70017a419d8e18b2a3141ab27989"><code>a22217f</code></a>
ci(lock-threads): use shared lock-threads workflow (<a
href="https://redirect.github.com/fastify/fastify/issues/6592">#6592</a>)</li>
<li><a
href="https://github.com/fastify/fastify/commit/1851f208e72be06ca419f2000dea63e540ff1ab0"><code>1851f20</code></a>
docs: update links (<a
href="https://redirect.github.com/fastify/fastify/issues/6593">#6593</a>)</li>
<li><a
href="https://github.com/fastify/fastify/commit/9cc5187be2dc7c38fd68d0d43541f16ed6d1e1ad"><code>9cc5187</code></a>
types: Allow port to be null in request type definition (<a
href="https://redirect.github.com/fastify/fastify/issues/6589">#6589</a>)</li>
<li><a
href="https://github.com/fastify/fastify/commit/722d83b0632387b853b218ae3a7da40cc46e2677"><code>722d83b</code></a>
docs: replace redirected npm.im http-errors link (<a
href="https://redirect.github.com/fastify/fastify/issues/6588">#6588</a>)</li>
<li><a
href="https://github.com/fastify/fastify/commit/a1413de2033b2b00dc1d3563d4f00a7e15ceab2d"><code>a1413de</code></a>
docs: fix incorrect code examples in Reply and Request reference (<a
href="https://redirect.github.com/fastify/fastify/issues/6582">#6582</a>)</li>
<li><a
href="https://github.com/fastify/fastify/commit/d7f01b600811172d7f7023bccc5e96583159202b"><code>d7f01b6</code></a>
docs: clarify content-type parser/schema mismatch is outside threat
model (<a
href="https://redirect.github.com/fastify/fastify/issues/6">#6</a>...</li>
<li><a
href="https://github.com/fastify/fastify/commit/a0649e92e93c1ad8b164020f61be5d5fa287d506"><code>a0649e9</code></a>
docs: update syntax markdown, absolute paths and links (<a
href="https://redirect.github.com/fastify/fastify/issues/6569">#6569</a>)</li>
<li><a
href="https://github.com/fastify/fastify/commit/d4779155286ea1d31c24dba1e90d7d478909382b"><code>d477915</code></a>
ci(link-checker): fix root-relative links resolution (<a
href="https://redirect.github.com/fastify/fastify/issues/6535">#6535</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/fastify/fastify/compare/v5.8.1...v5.8.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=fastify&package-manager=npm_and_yarn&previous-version=5.8.1&new-version=5.8.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/shakacode/react_on_rails/network/alerts).

</details>

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Justin Gordon <[email protected]>
Establish home-pro.md as the canonical Pro landing page with a route
map table, and add breadcrumb blockquotes on individual Pro feature
pages pointing back to it.

- Add "Route Map" table to home-pro.md mapping reader needs to
  "Start here" and "Then read" links across 5 Pro feature families
- Rewrite docs/README.md Pro section to funnel through home-pro.md
- Add Fragment Caching to the Pro features list (was missing)
- Add route map blockquotes to node-renderer.md, streaming-ssr.md,
  and fragment-caching.md with hyperlinked follow-on references
- Update quick-start.md Pro tip to point to home-pro.md as entry point
- Remove redundant duplicate link in quick-start.md bullet list

Co-Authored-By: Justin Gordon <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…nt guide

- Fix broken bottom border in sidecar diagram (stray ┘ → ┴ junction)
- Fix default import to named import matching package's actual export

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 28, 2026

size-limit report 📦

Path Size
react-on-rails/client bundled (gzip) 62.63 KB (0%)
react-on-rails/client bundled (gzip) (time) 62.63 KB (0%)
react-on-rails/client bundled (brotli) 53.7 KB (0%)
react-on-rails/client bundled (brotli) (time) 53.7 KB (0%)
react-on-rails-pro/client bundled (gzip) 63.65 KB (0%)
react-on-rails-pro/client bundled (gzip) (time) 63.65 KB (0%)
react-on-rails-pro/client bundled (brotli) 54.67 KB (0%)
react-on-rails-pro/client bundled (brotli) (time) 54.67 KB (0%)
registerServerComponent/client bundled (gzip) 127.46 KB (0%)
registerServerComponent/client bundled (gzip) (time) 127.46 KB (0%)
registerServerComponent/client bundled (brotli) 61.65 KB (0%)
registerServerComponent/client bundled (brotli) (time) 61.65 KB (0%)
wrapServerComponentRenderer/client bundled (gzip) 122.02 KB (0%)
wrapServerComponentRenderer/client bundled (gzip) (time) 122.02 KB (0%)
wrapServerComponentRenderer/client bundled (brotli) 56.77 KB (0%)
wrapServerComponentRenderer/client bundled (brotli) (time) 56.77 KB (0%)

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 28, 2026

Review: Node Renderer Container Deployment Guide

Overall this is a well-structured and practically useful guide. The architecture decision tree, memory sizing tables, and troubleshooting section are solid. A few issues to address before merge:

1. Worker count formula — unexplained divisor

The formula divides by 2 without explanation. Readers will ask: why half? The implicit assumption seems to be that SSR workers handle requests faster than Rails threads (Node is async and SSR completes quickly relative to a full Rails request cycle), so fewer workers can serve the same throughput. If that is the reasoning, it should be stated — otherwise the formula looks arbitrary and users tuning for high-load systems may under-provision.

2. Missing readinessProbe in Kubernetes examples

The probe examples show startupProbe and livenessProbe but omit readinessProbe. In Kubernetes, readinessProbe is what prevents the pod from receiving traffic before the renderer is ready — livenessProbe only controls restarts. For the sidecar pattern, the renderer container needs a readiness probe so the pod is only added to service endpoints once both containers are ready.

3. prerender_caching default correction in basics.md — good catch

The PR correctly changes the old claim (the default of prerender_caching is true) to state the actual default is false. The code confirms DEFAULT_PRERENDER_CACHING = false. This is a real bug fix in the existing docs.

4. ASCII diagram label shared memory (minor)

In the Single Container diagram, the shared memory label inside the container box could be misread as shared-memory IPC between processes. The intent is presumably shared cgroup memory limit. A label like shared OS resources or simply removing it would be less ambiguous.

5. gracefulWorkerRestartTimeout comment (minor)

The inline comment says Kill stuck workers after 30 seconds but per the JS config docs, this timeout fires when a worker does not complete its graceful restart within the window — not when a worker is otherwise stuck. Something like Force-kill if graceful restart takes more than 30 seconds is more accurate.

6. README minimum version update

The change from Ruby >= 3.2 / Node >= 20 to Ruby >= 3.0 (package minimum; CI tested: 3.2-3.4) / Node >= 18 (package minimum; CI tested: 20-22) is a useful clarification that separates declared minimums from what is exercised in CI.

Links verified

All internal cross-references in container-deployment.md resolve to existing files: js-configuration.md, error-reporting-and-tracing.md, heroku.md, pro/js-memory-leaks.md, pro/profiling-server-side-rendering-code.md, pro/troubleshooting.md. The custom-fastify-configuration anchor in js-configuration.md also exists.


A rough formula:

```text
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The /2 divisor is unexplained. Readers will reasonably ask why they need only half the calculated workers. If the reasoning is that each Node worker can serve requests faster than a Rails thread (because Node's event loop is async and SSR is typically fast), that assumption should be stated. Without it the formula looks arbitrary, and operators tuning for high-load environments may under-provision.

Consider adding a note like:

The /2 accounts for the fact that each Node worker can handle SSR requests faster than a Rails thread processes a full request, so fewer workers are needed to keep pace with the Rails request rate.

If the actual justification is different, state it explicitly.

Comment on lines +263 to +280
1. **Health check endpoint** — Add a `/health` route (see [JS Configuration: Custom Fastify Configuration](./js-configuration.md#custom-fastify-configuration)) and configure your container orchestrator to wait for it before routing traffic.
2. **Startup probe** — Configure a startup probe with a generous `initialDelaySeconds`:
```yaml
startupProbe:
httpGet:
path: /health
port: 3800
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 6
```
3. **Liveness probe** — Ensure the renderer is restarted if it becomes unresponsive:
```yaml
livenessProbe:
httpGet:
path: /health
port: 3800
periodSeconds: 10
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The startupProbe and livenessProbe examples are correct, but a readinessProbe is missing and is arguably the most important probe for this pattern. In Kubernetes, readinessProbe controls whether the pod receives traffic from the Service — livenessProbe only triggers container restarts. Without a readiness probe, traffic can reach the pod before the renderer is ready, causing real user-facing errors rather than just startup log noise.

Suggested addition:

readinessProbe:
  httpGet:
    path: /health
    port: 3800
  initialDelaySeconds: 5
  periodSeconds: 5
  failureThreshold: 3

Place this alongside the startupProbe and livenessProbe blocks.


```javascript
const config = {
allWorkersRestartInterval: 360, // Restart all workers every 6 hours
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The comment // Kill stuck workers after 30 seconds is slightly inaccurate. Per the JS config docs, gracefulWorkerRestartTimeout fires when a worker does not complete its graceful restart within the window — it is specifically a restart-completion deadline, not a general "stuck worker" detector.

Suggested change
allWorkersRestartInterval: 360, // Restart all workers every 6 hours
gracefulWorkerRestartTimeout: 30, // Force-kill if graceful restart takes >30 seconds

│ Container │
│ ┌────────┐ ┌──────────┐│
│ │ Rails │ │ Node ││
│ │ process│ │ Renderer ││
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The shared memory label inside the Single Container box can be misread as shared-memory IPC between the Rails and Node processes. The intent is that they share the same cgroup memory limit (OS-level resources), not that they communicate via shared memory.

Consider changing the label to shared OS resources or simply removing it to avoid confusion.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6db810523

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

| React version | `npm ls react` / `yarn why react` / `pnpm list react` / `bun pm why react` | 19.0.4+ (see [v16.2.0 release notes](../../oss/upgrading/release-notes/16.2.0.md) for security context) |
| React DOM version | `npm ls react-dom` / `yarn why react-dom` / `pnpm list react-dom` / `bun pm why react-dom` | Must match `react` version |
| `react-on-rails-rsc` | `npm ls react-on-rails-rsc` / `yarn why react-on-rails-rsc` / `pnpm list react-on-rails-rsc` / `bun pm why react-on-rails-rsc` | Compatible with the current Pro peer-dependency range |
| Node.js | `node --version` | 18+ |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore Node 20 minimum for RSC upgrade prerequisites

This prerequisite now says Node.js 18+, but the default Pro renderer path in this repo uses Fastify 5 and exits on Node <20 (packages/react-on-rails-pro-node-renderer/src/ReactOnRailsProNodeRenderer.ts, fastify5Supported guard at lines 20–32). Users following this RSC upgrade guide on Node 18 will pass the checklist but hit a startup failure when the Node renderer boots, so the documented minimum here should not be lower than the runtime-enforced minimum.

Useful? React with 👍 / 👎.

| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| React on Rails Pro gem | `bundle show react_on_rails_pro` | v16.4.0+ |
| React on Rails gem | `bundle show react_on_rails` | v16.4.0+ |
| React on Rails Pro npm | `npm ls react-on-rails-pro` / `yarn why react-on-rails-pro` / `pnpm list react-on-rails-pro` / `bun pm why react-on-rails-pro` | Matches gem version |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Replace unsupported bun pm why checks with valid Bun command

The new Bun verification commands are not valid: in this environment, bun pm --help lists subcommands such as ls, bin, and cache, but no why, and bun pm why react returns error: "why" unknown command. As written, Bun users cannot run the documented dependency checks in this table, so these commands should be changed to a supported Bun equivalent (for example bun pm ls-based checks).

Useful? React with 👍 / 👎.

The default `workersCount` is CPU count minus 1, which may over-allocate in containers. Set it explicitly:

```javascript
const config = {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The hardcoded fallback of '8' will surprise users with fewer CPUs — it contradicts the auto-detection logic documented in js-configuration.md (defaultWorkersCount() = CPU count - 1). Consider omitting the fallback entirely so that if the env var is unset, the reader is guided to size explicitly:

Suggested change
const config = {
workersCount: parseInt(process.env.RENDERER_WORKERS_COUNT, 10) || undefined, // fallback: CPU count - 1 (default)

Or simply show it without a fallback and add a note that the default kicks in when the variable is absent.

A rough formula:

```text
renderer_workers ≥ (WEB_CONCURRENCY × RAILS_MAX_THREADS × ssr_request_ratio) / 2
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The /2 divisor isn't explained, which makes the formula hard to apply confidently. A brief rationale would help — e.g. "SSR requests typically take ~2× longer than a plain JSON response, so the renderer doesn't need a 1:1 thread ratio with Rails". Without it, readers may blindly halve their worker count or ignore the formula entirely.


```javascript
// node-renderer.js
import { reactOnRailsProNodeRenderer } from 'react-on-rails-pro-node-renderer';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This example uses ESM import syntax, but the generator outputs (and js-configuration.md) use CommonJS require. A reader who copies this snippet directly into the generator-created client/node-renderer.js (which uses require) will get a SyntaxError.

Consider either switching to CommonJS to match the generator output:

const { reactOnRailsProNodeRenderer } = require('react-on-rails-pro-node-renderer');

or adding a brief note that ESM requires the file to be .mjs or the package to have "type": "module" (the same note that already exists in js-configuration.md under "Custom Fastify Configuration").

};

reactOnRailsProNodeRenderer(config);
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The health check returns { status: 'ok' } immediately, but it doesn't verify that any worker is actually ready to handle SSR requests. If Fastify is up but all workers are still initializing (the exact startup race condition described later in this doc), this probe passes prematurely and the problem recurs.

Worth noting this limitation, and pointing to a richer check (e.g. the renderer's own /health or a warm-up request) if one is available, or at minimum mentioning that this only verifies the HTTP server is up, not worker readiness.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 28, 2026

Review: docs/node-renderer-container-operations

Overall this is a well-structured, detailed operational guide. The architecture diagrams, resource tables, and troubleshooting steps are practical and clearly written. A few things worth addressing before merge:

Missing cross-reference: docs/pro/node-renderer.md "Further Reading" (not in this diff) doesn't link to the new guide. Anyone following the canonical Pro Node Renderer route will miss it. The links added to docs/README.md and basics.md are good, but node-renderer.md should have one too. Suggested line to add: - [Container deployment](../oss/building-features/node-renderer/container-deployment.md) — Sidecar vs. separate workloads, memory tuning, autoscaling, troubleshooting

Version bump scope: This PR bumps both gem versions from 16.5.0 to 16.5.1, but the CHANGELOG already has a 16.5.1 entry (dated 2026-03-27) covering unrelated bug fixes and this PR's doc additions aren't mentioned. If the bump is intentional, a brief changelog entry would keep the history complete.

Minor nits (filed inline):

  • Worker count example uses a hardcoded '8' fallback that contradicts the documented auto-detect default (CPU count minus 1)
  • Worker formula's / 2 divisor needs a one-line rationale
  • Host-binding code example uses ESM import while the generator output and other examples in this doc set use CommonJS require
  • The /health endpoint only checks that Fastify is up, not that workers are ready — worth a caveat given the startup race condition this very doc describes

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 40f6c900b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

```
2. Make sure you have **Node.js** version **14** or higher and **Yarn** installed.
3. Init node application and install the `react-on-rails-pro-node-renderer` package.
2. Make sure you have **Node.js 18+** and a JavaScript package manager such as **npm**, **pnpm**, **Yarn**, or **bun**.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Raise Node requirement to 20 for Node Renderer setup

This setup step tells users that Node.js 18+ is sufficient, but the default renderer install now pulls Fastify 5 (packages/react-on-rails-pro-node-renderer/package.json), and reactOnRailsProNodeRenderer exits when running on Node <20 (packages/react-on-rails-pro-node-renderer/src/ReactOnRailsProNodeRenderer.ts, fastify5Supported check). A user following this guide on Node 18 will complete installation and then hit a startup failure, so this prerequisite should be Node 20+ (or explicitly document the Fastify 4 override path).

Useful? React with 👍 / 👎.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@@ -0,0 +1,369 @@
# Node Renderer: Container Deployment

> **Pro Feature** — Available with [React on Rails Pro](https://pro.reactonrails.com).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale URL — the rest of the PR consistently migrates pro.reactonrails.comreactonrails.com/docs/pro/, but this file still uses the old domain.

Suggested change
> **Pro Feature** — Available with [React on Rails Pro](https://pro.reactonrails.com).
> **Pro Feature** — Available with [React on Rails Pro](https://reactonrails.com/docs/pro/).

- **Per-process visibility** — See exactly which process is consuming memory and causing OOM kills.
- **Independent resource limits** — Set separate CPU/memory limits for Rails and the Node Renderer.
- **Guaranteed version alignment** — Both containers use the same image on deploy.
- **Simpler networking** — Rails still connects via `localhost`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The localhost claim is accurate for Kubernetes pods (which share a network namespace) but misleading for Docker Compose. In a standard Compose file, each service has its own network namespace, so localhost in the Rails container only reaches Rails itself — the renderer would be unreachable.

Consider adding a clarification:

Note: In Docker Compose, containers in the same service definition do not share a network namespace by default. To replicate the Kubernetes sidecar model in Compose, use network_mode: "service:<renderer-service>" on the Rails container so both containers share the renderer's network namespace and can communicate via localhost. Otherwise, use the renderer's service hostname instead.

Comment on lines +266 to +284
2. **Startup probe** — Configure a startup probe with a generous `initialDelaySeconds`:
```yaml
startupProbe:
httpGet:
path: /health
port: 3800
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 6
```
3. **Liveness probe** — Ensure the renderer is restarted if it becomes unresponsive:
```yaml
livenessProbe:
httpGet:
path: /health
port: 3800
periodSeconds: 10
failureThreshold: 3
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The probe examples are missing a readinessProbe. Without one, Kubernetes will send traffic to a pod as soon as it passes the startup probe, but before the renderer has warmed up its internal worker pool and is truly ready to serve requests efficiently. The readiness probe is the correct gate for "should this pod receive traffic?".

Suggested addition after the livenessProbe block:

readinessProbe:
  httpGet:
    path: /health
    port: 3800
  initialDelaySeconds: 5
  periodSeconds: 5
  failureThreshold: 3

Also worth noting: for the sidecar case the probes above target the renderer container specifically. If the Rails container also needs a readiness probe, it should be configured separately.

Comment on lines +201 to +207
```javascript
const config = {
allWorkersRestartInterval: 360, // Restart all workers every 6 hours
delayBetweenIndividualWorkerRestarts: 2, // 2 minutes between each worker restart
gracefulWorkerRestartTimeout: 30, // Kill stuck workers after 30 seconds
};
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The units here are inconsistent and non-obvious: allWorkersRestartInterval and delayBetweenIndividualWorkerRestarts are in minutes, while gracefulWorkerRestartTimeout is in seconds. The inline comments convey the right human-readable meaning, but the units should be stated explicitly so readers know how to adjust the numbers. Consider adding unit labels:

Suggested change
```javascript
const config = {
allWorkersRestartInterval: 360, // Restart all workers every 6 hours
delayBetweenIndividualWorkerRestarts: 2, // 2 minutes between each worker restart
gracefulWorkerRestartTimeout: 30, // Kill stuck workers after 30 seconds
};
```
const config = {
allWorkersRestartInterval: 360, // minutes — restart all workers every 6 hours
delayBetweenIndividualWorkerRestarts: 2, // minutes between each worker restart
gracefulWorkerRestartTimeout: 30, // seconds — kill stuck workers after 30 s
};

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 28, 2026

Review posted via inline comments. See discussion threads on the PR for details on 4 issues: stale URL on line 3, Docker Compose localhost caveat on line 71, missing readinessProbe on lines 266-284, and restart interval units on lines 201-207.

justin808 added a commit that referenced this pull request Mar 29, 2026
## Summary

- Adds a comprehensive container deployment guide for the Node Renderer
covering three architecture options (single container, sidecar, separate
workloads) with a comparison table
- Includes practical examples: Dockerfile, Docker Compose, and full
Kubernetes sidecar manifest with startup/readiness/liveness probes
- Covers performance tuning (memory constraints, worker sizing formula,
rolling restarts), graceful shutdown, autoscaling considerations, and
ControlPlane-specific notes
- Adds cross-references from `docs/README.md` and
`node-renderer/basics.md`

Closes #2675

## Test plan

- [ ] Verify all internal doc links resolve correctly
- [ ] Confirm Prettier formatting passes
- [ ] Review YAML and Dockerfile examples for accuracy
- [ ] Check lychee link checker passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are documentation-only plus minor CI link-checker
tuning (retries/excludes) with no runtime code impact.
> 
> **Overview**
> Adds a new **Pro** documentation guide,
`docs/oss/building-features/node-renderer/container-deployment.md`,
covering containerized Node Renderer deployment patterns (single
container/sidecar/separate workload) with concrete Dockerfile, Docker
Compose, and Kubernetes probe/sidecar examples plus
tuning/troubleshooting guidance.
> 
> Surfaces the new guide via links from `docs/README.md` and the Node
Renderer `basics.md` references.
> 
> Tweaks `.lychee.toml` to reduce CI link-check flakiness by increasing
retry settings and excluding an additional intermittently failing URL
(`hvmn.com`), and clarifies the comment for excluded deleted GitHub
accounts.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
930dc7f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Added a comprehensive Pro guide for deploying the Node Renderer in
containerized environments (deployment patterns, networking,
Docker/Compose and Kubernetes examples, resource and memory tuning,
health checks, graceful shutdown, autoscaling, error handling,
troubleshooting) and surfaced it in the docs navigation and references.
* **Chores**
* Increased CI transient-error retry settings and expanded
link-exclusion patterns to reduce flaky external URL failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
justin808 added a commit that referenced this pull request Mar 29, 2026
- Adds a comprehensive container deployment guide for the Node Renderer
covering three architecture options (single container, sidecar, separate
workloads) with a comparison table
- Includes practical examples: Dockerfile, Docker Compose, and full
Kubernetes sidecar manifest with startup/readiness/liveness probes
- Covers performance tuning (memory constraints, worker sizing formula,
rolling restarts), graceful shutdown, autoscaling considerations, and
ControlPlane-specific notes
- Adds cross-references from `docs/README.md` and
`node-renderer/basics.md`

Closes #2675

- [ ] Verify all internal doc links resolve correctly
- [ ] Confirm Prettier formatting passes
- [ ] Review YAML and Dockerfile examples for accuracy
- [ ] Check lychee link checker passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are documentation-only plus minor CI link-checker
tuning (retries/excludes) with no runtime code impact.
>
> **Overview**
> Adds a new **Pro** documentation guide,
`docs/oss/building-features/node-renderer/container-deployment.md`,
covering containerized Node Renderer deployment patterns (single
container/sidecar/separate workload) with concrete Dockerfile, Docker
Compose, and Kubernetes probe/sidecar examples plus
tuning/troubleshooting guidance.
>
> Surfaces the new guide via links from `docs/README.md` and the Node
Renderer `basics.md` references.
>
> Tweaks `.lychee.toml` to reduce CI link-check flakiness by increasing
retry settings and excluding an additional intermittently failing URL
(`hvmn.com`), and clarifies the comment for excluded deleted GitHub
accounts.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
930dc7f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

* **Documentation**
* Added a comprehensive Pro guide for deploying the Node Renderer in
containerized environments (deployment patterns, networking,
Docker/Compose and Kubernetes examples, resource and memory tuning,
health checks, graceful shutdown, autoscaling, error handling,
troubleshooting) and surfaced it in the docs navigation and references.
* **Chores**
* Increased CI transient-error retry settings and expanded
link-exclusion patterns to reduce flaky external URL failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
@justin808 justin808 added the Metr-Pending Pending Metr tracking label Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Metr-Pending Pending Metr tracking

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants