Skip to content

Add a server-side cluster harness for Bottleneck - #2

Merged
Megapixel99 merged 1 commit into
mainfrom
experiment/bottleneck-cluster
Aug 18, 2026
Merged

Add a server-side cluster harness for Bottleneck#2
Megapixel99 merged 1 commit into
mainfrom
experiment/bottleneck-cluster

Conversation

@Megapixel99

Copy link
Copy Markdown
Owner

Generalises this repo's politeness test and points it at Bottleneck, the most-downloaded rate limiter on npm (8.2M/week).

The claim

Bottleneck's default datastore: "local" is per-process, so under Node's cluster module six workers deliver 7x the configured rate while every limiter self-reports the correct ~497 ms spacing.

Measured at the server with minTime: 500, 6 workers, 6 requests each:

arm min gap gaps under minTime rate limiter's self-report
1 worker, local (control) 487.6 ms 0/5 2.01/s 498.4 ms
6 workers, local (default) 0.1 ms 30/35 14.04/s 495.8 ms
6 workers, ioredis (control) 483.7 ms 0/35 2.00/s n/a

Three repeats of the failing arm gave 30, 30 and 31 violations out of 35. The aggregate rate tracks worker count: 1.00x, 2.21x, 4.61x, 7.02x, 9.30x at 1/2/4/6/8 workers.

Why it is not a bug report

local means local, and Bottleneck documents clustering as a Redis feature. LocalDatastore keeps _nextRequest as an instance field, and I grepped the source for process.send, worker_threads, Atomics and SharedArrayBuffer and found none: every "cluster" in that codebase is Redis Cluster. So the library does exactly what it says.

The finding is that the default degrades silently under cluster, and that nothing in either project's tests is shaped to notice: no file in Bottleneck's 15 test files contains createServer or .listen(, so every assertion is against the limiter's own timing. The README's only word on multi-process is one line saying clustering uses Redis.

Bottleneck's last commit is 2020-07-21, so this is a note for users rather than something expecting a fix upstream.

Both controls are load-bearing

The 1-worker arm shows the harness measures spacing correctly when spacing is happening. The ioredis arm shows it passes a correctly coordinated limiter across the same six workers. Without both, "0.1 ms" is indistinguishable from a broken test, which is the failure mode the original politeness bug had in the first place.

Notes

Self-contained in bottleneck-cluster/, with its own package.json, so it does not touch the crawler or its dependencies. Node v24.11.1, Bottleneck 2.19.5, macOS; Redis via docker run redis:7-alpine.

A write-up is in a separate PR on the site repo and links back here.

Generalises this repo's politeness test: assert on what the server
received, not on what the limiter reported. Bottleneck's default
local datastore is per-process, so 6 cluster workers deliver 7x the
configured rate while every limiter self-reports ~497ms spacing.
Includes 1-worker and ioredis controls.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Megapixel99
Megapixel99 merged commit 04a51cb into main Aug 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant