docs: Node Renderer container deployment guide#2675
Conversation
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.
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdded 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
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR adds a new Key points:
Confidence Score: 3/5
Important Files Changed
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]
Last reviewed commit: "docs: add Node Rende..." |
There was a problem hiding this comment.
💡 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".
Review: Node Renderer Container Deployment GuideGood 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
Suggestions
|
There was a problem hiding this comment.
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
bashorshellas 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.mdaround
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 orshell) 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.mdaround
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 openingfence.</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.mdaround
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.mdaround
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 fromtobash (orshell) 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 usebash.</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.mdaround
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 becomestext (orplaintext)
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 to0.0.0.0:" is
incorrect and conflicts with the later note that sidecars can uselocalhost;
update that sentence to clarify that when the Node Renderer runs as a true
sidecar (shared pod network namespace) binding tolocalhostis acceptable, but
when running as a separate workload or in Docker Compose (separate network
namespaces) you must bind to0.0.0.0; reference the exact phrasing "By
default, the Node Renderer binds tolocalhost..." 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 orshell) 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 openingfence.- 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 fromtobash (orshell) 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 usebash.- 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 (orrenders 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📒 Files selected for processing (3)
docs/README.mddocs/oss/building-features/node-renderer/basics.mddocs/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.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
docs/oss/building-features/node-renderer/container-deployment.md (1)
107-107:⚠️ Potential issue | 🟡 MinorClarify 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.0is 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
📒 Files selected for processing (1)
docs/oss/building-features/node-renderer/container-deployment.md
There was a problem hiding this comment.
💡 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".
Review: Node Renderer Container Deployment GuideGood 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:
Suggestions:
Verified:
|
## 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 -->
## 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 -->
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
PR Review: Node Renderer Container Deployment GuideThis 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 merge1. Named import should be default import (copy-paste impact) Line 111 uses 2. Sidecar host binding is technically incorrect The guide states that both sidecar and separate-workload configurations need Minor issues worth addressing
|
## 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 "fastify" to "instance" 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 "chore: upgrade borp to v1.0.0" 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 /> [](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]>
size-limit report 📦
|
Review: Node Renderer Container Deployment GuideOverall 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 |
There was a problem hiding this comment.
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
/2accounts 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.
| 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 |
There was a problem hiding this comment.
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: 3Place this alongside the startupProbe and livenessProbe blocks.
|
|
||
| ```javascript | ||
| const config = { | ||
| allWorkersRestartInterval: 360, // Restart all workers every 6 hours |
There was a problem hiding this comment.
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.
| allWorkersRestartInterval: 360, // Restart all workers every 6 hours | |
| gracefulWorkerRestartTimeout: 30, // Force-kill if graceful restart takes >30 seconds |
| │ Container │ | ||
| │ ┌────────┐ ┌──────────┐│ | ||
| │ │ Rails │ │ Node ││ | ||
| │ │ process│ │ Renderer ││ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
💡 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+ | |
There was a problem hiding this comment.
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 | |
There was a problem hiding this comment.
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 = { |
There was a problem hiding this comment.
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:
| 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 |
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
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); | ||
| ``` |
There was a problem hiding this comment.
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.
Review: docs/node-renderer-container-operationsOverall 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: 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):
|
There was a problem hiding this comment.
💡 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**. |
There was a problem hiding this comment.
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). | |||
There was a problem hiding this comment.
Stale URL — the rest of the PR consistently migrates pro.reactonrails.com → reactonrails.com/docs/pro/, but this file still uses the old domain.
| > **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`. |
There was a problem hiding this comment.
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 vialocalhost. Otherwise, use the renderer's service hostname instead.
| 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 | ||
| ``` |
There was a problem hiding this comment.
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: 3Also 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.
| ```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 | ||
| }; | ||
| ``` |
There was a problem hiding this comment.
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:
| ```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 | |
| }; |
|
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. |
## 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]>
- 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]>
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
0.0.0.0requirement for container environmentsNODE_OPTIONS --max-old-space-size, worker count tuning, rolling restarts, jemalloc for RailsERR_STREAM_PREMATURE_CLOSEstartup errors, OOM exit codes, health checksCross-references added
docs/oss/building-features/node-renderer/basics.md— link in Referencesdocs/README.md— link in Pro docs sectionCC: @justin808 @sergey-alekseev @AbanoubGhadworban
Summary by CodeRabbit