Commit c7b54be
## Why
The dominant suspects for the streamed RSC `responseEnd` tail (Discover
median +3.2% vs Inertia in the 2026-06-24 hosted run) are Node renderer
round-trip overhead, cold/under-warmed workers, and per-request
Rails↔renderer connection setup. The issue asked for documented,
measured guidance on the levers that move that tail: warmup, pool
sizing, and keep-alive. Closes #4240.
## Key finding: keep-alive is already implemented, but the docs said
otherwise
While investigating, I found the configuration doc was **materially
stale**. `configuration-pro.md` stated:
> `renderer_http_pool_size` — *"Currently has no effect. The async-http
adapter creates a new client per request, so this pool limit is never
reached… planned persistent connection support (see issue #3283)."*
The code tells a different story. `RendererHttpClient#with_client` /
`#scheduler_scoped_client` reuse a persistent `Async::HTTP::Client`
across requests within a `Fiber.scheduler`, with an inline comment:
*"Connection pool (limit) is now effective — multiple streams share
pooled connections."* The streaming helper runs inside `Sync {}`, so
**the streaming path already gets HTTP/2 keep-alive / connection reuse**
— issue #3283 is done. `renderer_http_keep_alive_timeout` is already
deprecated/ignored in `configuration.rb`.
So the keep-alive "investigation" deliverable resolves to: **the
capability exists; the docs were wrong.** This PR corrects them and
consolidates the tuning guidance.
## What changed (docs only)
`docs/oss/configuration/configuration-pro.md`:
- **Corrected** the `renderer_http_pool_size` comment to describe the
implemented behavior (persistent HTTP/2 reuse within the streaming
`Fiber.scheduler`; the limit bounds concurrent multiplexed streams).
- **Added** a "Renderer Performance Tuning for Streamed RSC" section:
1. **Warmup** — pre-warm every worker so the first measured render isn't
cold (cross-references the existing [health-checks `/ready` cold-start
contract](docs/oss/building-features/node-renderer/health-checks.md),
incl. the `workersCount > 1` fan-out caveat).
2. **Pool sizing** — size `renderer_http_pool_size` (Rails) against
`workersCount` (renderer) and Puma concurrency, with a comparison table.
3. **Keep-alive** — document that connection reuse is automatic on the
streaming path and that `renderer_http_keep_alive_timeout` is
deprecated.
Measurement ties back to the streamed `Server-Timing` metrics
(`ror_renderer_prepare`, `ror_stream_shell`) added for #4239.
## Acceptance criteria status
- [x] Documented renderer warmup and pool-sizing guidance for streamed
RSC routes.
- [x] Verified keep-alive / pooled connection between Rails and the
renderer — confirmed in code (`scheduler_scoped_client`, persistent
`Async::HTTP::Client`), and the stale doc claiming otherwise is
corrected.
- [ ] **Re-run the demo benchmark to close the Discover `responseEnd`
regression / improve p95** — requires the separate
[`react-on-rails-demo-gumroad-rsc`](https://github.com/shakacode/react-on-rails-demo-gumroad-rsc)
hosted environment. Maintainer handoff; this PR delivers the guidance +
corrected knobs the demo needs.
## Testing
Docs-only change. Locally: `node script/generate-llms-full.mjs
--validate` ✓, `script/check-docs-sidebar origin/main` ✓ (no new pages),
Prettier ✓.
## Decision log
- **Non-blocking:** Add a new warmup knob/rake task vs. document.
**Decision:** document — warmup is a deploy-orchestration concern
already served by the `/ready` health endpoint and the render path; a
redundant knob would add surface without value. Keep-alive and pool-size
knobs already exist. **Review later:** add a first-class warmup rake
task if users ask.
- **Non-blocking:** CHANGELOG entry placed under **Changed** (not Added)
since the core change is a doc correction. Also avoids a merge conflict
with the #4239/#4238 batch entries under Added.
## Related
Streamed-RSC performance batch with #4251 (Server-Timing, #4239) and
#4252 (compression, #4238). No source-file overlap — this PR touches
only `configuration-pro.md` + CHANGELOG.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Updated streamed React Server Components guidance to clarify how
`renderer_http_pool_size` limits concurrent async-http TCP connection
pooling (effective on the streaming path via HTTP/2 reuse) and how
scheduler lifetime impacts connection reuse/concurrency.
* Added “Renderer Performance Tuning for Streamed RSC” notes covering
streamed `responseEnd` tail-latency contributors and tuning levers
(renderer worker pre-warming, coordinated worker/pool sizing, and
`ssr_timeout` as idle socket timeout), plus Rails↔renderer keep-alive
behavior.
* Revised upgrade and changelog entries:
`renderer_http_keep_alive_timeout` is deprecated/ignored (with
deprecation warning when non-`nil`), and renderer connection drops
surface immediately via the pro error path (with no implicit transport
retry).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 67d12aa commit c7b54be
5 files changed
Lines changed: 143 additions & 41 deletions
File tree
- docs
- oss/configuration
- pro
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
270 | 270 | | |
271 | 271 | | |
272 | 272 | | |
273 | | - | |
274 | | - | |
| 273 | + | |
275 | 274 | | |
276 | 275 | | |
277 | 276 | | |
| |||
294 | 293 | | |
295 | 294 | | |
296 | 295 | | |
| 296 | + | |
297 | 297 | | |
298 | 298 | | |
299 | 299 | | |
| |||
361 | 361 | | |
362 | 362 | | |
363 | 363 | | |
364 | | - | |
| 364 | + | |
365 | 365 | | |
366 | 366 | | |
367 | 367 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
| 85 | + | |
86 | 86 | | |
87 | | - | |
| 87 | + | |
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| |||
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
101 | 106 | | |
102 | 107 | | |
103 | 108 | | |
| |||
172 | 177 | | |
173 | 178 | | |
174 | 179 | | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
175 | 221 | | |
176 | 222 | | |
177 | 223 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
392 | 392 | | |
393 | 393 | | |
394 | 394 | | |
395 | | - | |
396 | | - | |
397 | | - | |
398 | | - | |
399 | | - | |
400 | | - | |
401 | | - | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
402 | 402 | | |
403 | 403 | | |
404 | 404 | | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
411 | 416 | | |
412 | 417 | | |
413 | 418 | | |
| |||
0 commit comments