Skip to content

Commit afea8fe

Browse files
committed
Correct renderer pool sizing docs
1 parent 13668da commit afea8fe

4 files changed

Lines changed: 34 additions & 32 deletions

File tree

docs/oss/configuration/configuration-pro.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,13 @@ ReactOnRailsPro.configure do |config|
9494
# Default for `renderer_use_fallback_exec_js` is true.
9595
config.renderer_use_fallback_exec_js = false
9696

97-
# Maximum number of concurrent HTTP/2 streams to the Node renderer per async-http client.
97+
# Maximum number of concurrent TCP connections in the async-http client pool to the Node renderer.
9898
# When a Fiber.scheduler already exists before the renderer request enters `Sync {}`, the
9999
# client is reused across requests within that long-lived scheduler (persistent connection /
100-
# keep-alive, issue #3283), so this limit bounds multiplexed renders on the pooled client.
100+
# keep-alive, issue #3283), so this limit bounds pooled TCP connections to the renderer.
101101
# Under standard Puma streaming, `Sync {}` creates a per-request scheduler and the client is
102-
# cleaned up when that response ends; the limit still applies within the streaming request.
102+
# cleaned up when that response ends; the connection-pool limit still applies within the
103+
# streaming request.
103104
# Without a scheduler (non-streaming paths), a client is created per request. See
104105
# "Renderer Performance Tuning for Streamed RSC" below.
105106
# Default for `renderer_http_pool_size` is 10
@@ -193,22 +194,22 @@ Full warm-up patterns (Kubernetes probes, `postStart` hooks, the `/ready` cold-s
193194

194195
Two independent limits gate renderer throughput:
195196

196-
| Setting | Where | Default | Governs |
197-
| --------------------------------------------------------------------------------------------------- | -------- | -------- | ---------------------------------------------------------------- |
198-
| [`workersCount`](../building-features/node-renderer/js-configuration.md) / `RENDERER_WORKERS_COUNT` | Renderer | CPUs − 1 | How many renders the renderer can execute concurrently. |
199-
| `renderer_http_pool_size` | Rails | 10 | Max concurrent HTTP/2 streams Rails multiplexes to the renderer. |
197+
| Setting | Where | Default | Governs |
198+
| --------------------------------------------------------------------------------------------------- | -------- | -------- | ------------------------------------------------------------------ |
199+
| [`workersCount`](../building-features/node-renderer/js-configuration.md) / `RENDERER_WORKERS_COUNT` | Renderer | CPUs − 1 | How many renders the renderer can execute concurrently. |
200+
| `renderer_http_pool_size` | Rails | 10 | Max TCP connections in the async-http client pool to the renderer. |
200201

201202
Guidance:
202203

203-
- Keep `renderer_http_pool_size` close to (and generally not far above) `workersCount`; sending many more concurrent streams than there are workers just queues renders at the renderer.
204+
- Keep `renderer_http_pool_size` close to (and generally not far above) `workersCount`; sending many more concurrent renderer requests than there are workers just queues renders at the renderer while adding socket overhead.
204205
- Account for your Rails concurrency: with many Puma threads/workers all streaming, a renderer with only one or two workers becomes the bottleneck. Scale `workersCount` (and renderer replicas) to your real concurrent streamed-render load.
205-
- Raise `ssr_timeout` for long-running streamed responses — it is the socket idle timeout for the streaming connection. It fires when the renderer sends no data for `ssr_timeout` seconds, not when the total response duration exceeds that value.
206+
- Raise `ssr_timeout` for long-running streamed responses — it is the per-read socket timeout on the renderer connection. It fires when the renderer sends no data during a single read for `ssr_timeout` seconds, not when the total response duration exceeds that value.
206207

207208
### 3. Rails ↔ renderer keep-alive (persistent on Falcon/async scheduler; per-request on standard Puma)
208209

209210
Connection reuse is automatic when the renderer request runs under a long-lived `Fiber.scheduler`, such as Falcon or Puma configured with an async scheduler. In that setup, the async-http client is stored on the scheduler and reused across streaming requests, so HTTP/2 connections stay alive and renders multiplex over them instead of paying TCP/TLS setup per request (issue #3283). No React on Rails configuration is required to enable this.
210211

211-
Under standard Puma, the streaming helper's `Sync {}` block creates a per-request scheduler. The async-http client is cleaned up when that streaming response ends, so connection reuse does not persist across consecutive Rails requests. The benefit is still meaningful inside a single streamed response: renderer calls in that response can share the same client lifecycle and `renderer_http_pool_size` still bounds concurrent HTTP/2 streams.
212+
Under standard Puma, the streaming helper's `Sync {}` block creates a per-request scheduler. The async-http client is cleaned up when that streaming response ends, so connection reuse does not persist across consecutive Rails requests. The benefit is still meaningful inside a single streamed response: renderer calls in that response can share the same client lifecycle and `renderer_http_pool_size` still bounds TCP connections created during the request.
212213

213214
`config.renderer_http_keep_alive_timeout` is **deprecated** and ignored: the async-http adapter manages connection lifecycle automatically (connections are reused within the scheduler and cleaned up when it ends). Setting it to a non-`nil` value logs a deprecation warning; `nil` is accepted silently.
214215

docs/pro/updating.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -392,12 +392,12 @@ Before upgrading:
392392
read timeout on each renderer socket. It no longer wraps the entire request as a single task-level timeout.
393393
- Treat `config.renderer_http_pool_timeout` as the TCP connect timeout. After the socket connects, individual reads
394394
are bounded by `ssr_timeout`.
395-
- Treat `config.renderer_http_pool_size` as an HTTP/2 stream limit on the async-http client, not as a
396-
process-wide renderer connection count. With a long-lived `Fiber.scheduler` (for example Falcon or Puma configured
397-
with an async scheduler), the client is reused across renderer requests within that scheduler and the setting bounds
398-
multiplexed renders on the pooled client. Under standard Puma streaming, `Sync {}` creates a per-request scheduler
399-
and cleans up the client when that streaming response ends, so reuse does not persist across consecutive Rails
400-
requests. Setting it to `nil` keeps the default stream limit; it does not make the async-http client unlimited.
395+
- Treat `config.renderer_http_pool_size` as the TCP connection-pool limit for the async-http client, not as an HTTP/2
396+
stream limit. With a long-lived `Fiber.scheduler` (for example Falcon or Puma configured with an async scheduler),
397+
the client is reused across renderer requests within that scheduler and the setting bounds pooled connections to the
398+
renderer. Under standard Puma streaming, `Sync {}` creates a per-request scheduler and cleans up the client when that
399+
streaming response ends, so reuse does not persist across consecutive Rails requests. Setting it to `nil` keeps the
400+
default pool limit; it does not make the async-http client unlimited.
401401
- Expect renderer connection drops to surface immediately as `ReactOnRailsPro::Error`/connection failures. HTTPX
402402
previously performed one implicit transport retry for some connection drops; the async-http adapter uses
403403
`retries: 0` and leaves retry policy to the existing bundle-upload retry loop and caller behavior.

llms-full-pro.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -593,12 +593,12 @@ Before upgrading:
593593
read timeout on each renderer socket. It no longer wraps the entire request as a single task-level timeout.
594594
- Treat `config.renderer_http_pool_timeout` as the TCP connect timeout. After the socket connects, individual reads
595595
are bounded by `ssr_timeout`.
596-
- Treat `config.renderer_http_pool_size` as an HTTP/2 stream limit on the async-http client, not as a
597-
process-wide renderer connection count. With a long-lived `Fiber.scheduler` (for example Falcon or Puma configured
598-
with an async scheduler), the client is reused across renderer requests within that scheduler and the setting bounds
599-
multiplexed renders on the pooled client. Under standard Puma streaming, `Sync {}` creates a per-request scheduler
600-
and cleans up the client when that streaming response ends, so reuse does not persist across consecutive Rails
601-
requests. Setting it to `nil` keeps the default stream limit; it does not make the async-http client unlimited.
596+
- Treat `config.renderer_http_pool_size` as the TCP connection-pool limit for the async-http client, not as an HTTP/2
597+
stream limit. With a long-lived `Fiber.scheduler` (for example Falcon or Puma configured with an async scheduler),
598+
the client is reused across renderer requests within that scheduler and the setting bounds pooled connections to the
599+
renderer. Under standard Puma streaming, `Sync {}` creates a per-request scheduler and cleans up the client when that
600+
streaming response ends, so reuse does not persist across consecutive Rails requests. Setting it to `nil` keeps the
601+
default pool limit; it does not make the async-http client unlimited.
602602
- Expect renderer connection drops to surface immediately as `ReactOnRailsPro::Error`/connection failures. HTTPX
603603
previously performed one implicit transport retry for some connection drops; the async-http adapter uses
604604
`retries: 0` and leaves retry policy to the existing bundle-upload retry loop and caller behavior.

llms-full.txt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18095,12 +18095,13 @@ ReactOnRailsPro.configure do |config|
1809518095
# Default for `renderer_use_fallback_exec_js` is true.
1809618096
config.renderer_use_fallback_exec_js = false
1809718097

18098-
# Maximum number of concurrent HTTP/2 streams to the Node renderer per async-http client.
18098+
# Maximum number of concurrent TCP connections in the async-http client pool to the Node renderer.
1809918099
# When a Fiber.scheduler already exists before the renderer request enters `Sync {}`, the
1810018100
# client is reused across requests within that long-lived scheduler (persistent connection /
18101-
# keep-alive, issue #3283), so this limit bounds multiplexed renders on the pooled client.
18101+
# keep-alive, issue #3283), so this limit bounds pooled TCP connections to the renderer.
1810218102
# Under standard Puma streaming, `Sync {}` creates a per-request scheduler and the client is
18103-
# cleaned up when that response ends; the limit still applies within the streaming request.
18103+
# cleaned up when that response ends; the connection-pool limit still applies within the
18104+
# streaming request.
1810418105
# Without a scheduler (non-streaming paths), a client is created per request. See
1810518106
# "Renderer Performance Tuning for Streamed RSC" below.
1810618107
# Default for `renderer_http_pool_size` is 10
@@ -18194,22 +18195,22 @@ Full warm-up patterns (Kubernetes probes, `postStart` hooks, the `/ready` cold-s
1819418195

1819518196
Two independent limits gate renderer throughput:
1819618197

18197-
| Setting | Where | Default | Governs |
18198-
| --------------------------------------------------------------------------------------------------- | -------- | -------- | ---------------------------------------------------------------- |
18199-
| [`workersCount`](../building-features/node-renderer/js-configuration.md) / `RENDERER_WORKERS_COUNT` | Renderer | CPUs − 1 | How many renders the renderer can execute concurrently. |
18200-
| `renderer_http_pool_size` | Rails | 10 | Max concurrent HTTP/2 streams Rails multiplexes to the renderer. |
18198+
| Setting | Where | Default | Governs |
18199+
| --------------------------------------------------------------------------------------------------- | -------- | -------- | ------------------------------------------------------------------ |
18200+
| [`workersCount`](../building-features/node-renderer/js-configuration.md) / `RENDERER_WORKERS_COUNT` | Renderer | CPUs − 1 | How many renders the renderer can execute concurrently. |
18201+
| `renderer_http_pool_size` | Rails | 10 | Max TCP connections in the async-http client pool to the renderer. |
1820118202

1820218203
Guidance:
1820318204

18204-
- Keep `renderer_http_pool_size` close to (and generally not far above) `workersCount`; sending many more concurrent streams than there are workers just queues renders at the renderer.
18205+
- Keep `renderer_http_pool_size` close to (and generally not far above) `workersCount`; sending many more concurrent renderer requests than there are workers just queues renders at the renderer while adding socket overhead.
1820518206
- Account for your Rails concurrency: with many Puma threads/workers all streaming, a renderer with only one or two workers becomes the bottleneck. Scale `workersCount` (and renderer replicas) to your real concurrent streamed-render load.
18206-
- Raise `ssr_timeout` for long-running streamed responses — it is the socket idle timeout for the streaming connection. It fires when the renderer sends no data for `ssr_timeout` seconds, not when the total response duration exceeds that value.
18207+
- Raise `ssr_timeout` for long-running streamed responses — it is the per-read socket timeout on the renderer connection. It fires when the renderer sends no data during a single read for `ssr_timeout` seconds, not when the total response duration exceeds that value.
1820718208

1820818209
### 3. Rails ↔ renderer keep-alive (persistent on Falcon/async scheduler; per-request on standard Puma)
1820918210

1821018211
Connection reuse is automatic when the renderer request runs under a long-lived `Fiber.scheduler`, such as Falcon or Puma configured with an async scheduler. In that setup, the async-http client is stored on the scheduler and reused across streaming requests, so HTTP/2 connections stay alive and renders multiplex over them instead of paying TCP/TLS setup per request (issue #3283). No React on Rails configuration is required to enable this.
1821118212

18212-
Under standard Puma, the streaming helper's `Sync {}` block creates a per-request scheduler. The async-http client is cleaned up when that streaming response ends, so connection reuse does not persist across consecutive Rails requests. The benefit is still meaningful inside a single streamed response: renderer calls in that response can share the same client lifecycle and `renderer_http_pool_size` still bounds concurrent HTTP/2 streams.
18213+
Under standard Puma, the streaming helper's `Sync {}` block creates a per-request scheduler. The async-http client is cleaned up when that streaming response ends, so connection reuse does not persist across consecutive Rails requests. The benefit is still meaningful inside a single streamed response: renderer calls in that response can share the same client lifecycle and `renderer_http_pool_size` still bounds TCP connections created during the request.
1821318214

1821418215
`config.renderer_http_keep_alive_timeout` is **deprecated** and ignored: the async-http adapter manages connection lifecycle automatically (connections are reused within the scheduler and cleaned up when it ends). Setting it to a non-`nil` value logs a deprecation warning; `nil` is accepted silently.
1821518216

0 commit comments

Comments
 (0)