Skip to content

Commit 957d938

Browse files
feat: cap cluster worker count via IFRAMELY_WORKERS_COUNT (#4)
graceful-cluster defaults to os.cpus().length workers, which is the HOST node's vCPU count and ignores the container's CPU limit. On large nodes (e.g. 32 vCPU) this forks ~32 workers, each independently loading ~1886 domains + Redis + Secrets Manager, exhausting the pod memory limit -> OOMKilled/CrashLoopBackOff. Pass workersCount to GracefulCluster.start from CONFIG.CLUSTER_WORKERS_COUNT, settable via IFRAMELY_WORKERS_COUNT (alias IFRAMELY_WORKERS). When unset, behaviour is unchanged (falls back to os.cpus().length). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a70dac1 commit 957d938

2 files changed

Lines changed: 18 additions & 0 deletions

File tree

cluster.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ process.title = 'iframely-cluster';
55

66
GracefulCluster.start({
77
log: sysUtils.log,
8+
// When undefined, graceful-cluster falls back to os.cpus().length, which is
9+
// the HOST node's vCPU count and ignores the container's CPU limit — forking
10+
// far too many workers on large nodes (each loads ~1886 domains + Redis +
11+
// Secrets Manager). Cap it via IFRAMELY_WORKERS_COUNT (see config.loader.js).
12+
workersCount: CONFIG.CLUSTER_WORKERS_COUNT,
813
shutdownTimeout: CONFIG.SHUTDOWN_TIMEOUT,
914
disableGraceful: CONFIG.DEBUG,
1015
restartOnTimeout: CONFIG.CLUSTER_WORKER_RESTART_ON_PERIOD,

config.loader.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ globalConfig = globalConfig && globalConfig.default;
3333
// REDIS_PORT_KEY JSON key for port (default: REDIS_PORT)
3434
//
3535
// Cluster worker tuning
36+
// IFRAMELY_WORKERS_COUNT number of cluster workers (default: os.cpus().length)
37+
// alias: IFRAMELY_WORKERS
3638
// IFRAMELY_WORKER_MAX_MEMORY_MB per-worker memory before restart, MB (default: 120)
3739
// IFRAMELY_WORKER_RESTART_PERIOD_SEC periodic worker restart interval, seconds (default: 28800)
3840
// ---------------------------------------------------------------------------
@@ -113,4 +115,15 @@ if (process.env.IFRAMELY_WORKER_RESTART_PERIOD_SEC) {
113115
}
114116
}
115117

118+
// Number of cluster workers. Without this, graceful-cluster uses os.cpus().length
119+
// (the HOST node's vCPU count), which on large nodes forks far more workers than
120+
// the container's CPU/memory can sustain -> OOMKilled. IFRAMELY_WORKERS is
121+
// accepted as an alias.
122+
if (process.env.IFRAMELY_WORKERS_COUNT || process.env.IFRAMELY_WORKERS) {
123+
var workersCount = parseInt(process.env.IFRAMELY_WORKERS_COUNT || process.env.IFRAMELY_WORKERS, 10);
124+
if (!isNaN(workersCount) && workersCount > 0) {
125+
envOverrides.CLUSTER_WORKERS_COUNT = workersCount;
126+
}
127+
}
128+
116129
export default {...iframelyConfig, ...globalConfig, ...envOverrides};

0 commit comments

Comments
 (0)