Add a server-side cluster harness for Bottleneck - #2
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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'sclustermodule 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:local(control)local(default)ioredis(control)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
localmeans local, and Bottleneck documents clustering as a Redis feature.LocalDatastorekeeps_nextRequestas an instance field, and I grepped the source forprocess.send,worker_threads,AtomicsandSharedArrayBufferand 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 containscreateServeror.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
ioredisarm 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 ownpackage.json, so it does not touch the crawler or its dependencies. Node v24.11.1, Bottleneck 2.19.5, macOS; Redis viadocker run redis:7-alpine.A write-up is in a separate PR on the site repo and links back here.