npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dynoscale-node

v1.0.0

Published

Scaling agent for Node.js apps on Heroku. Reports web and worker queue time to the Dynoscale add-on.

Readme

Dynoscale Node

Scaling agent for Node.js apps on Heroku. It reports request queue time, and optionally BullMQ queue latency, to the Dynoscale add-on.

Queue time is how long a request waits before your app starts handling it. Dynoscale scales from that signal, so a slow handler does not by itself add dynos. This package follows the same reporting protocol as dynoscale_ruby.

Web and worker dynos have to run on Standard or Performance dynos for autoscaling to take effect.

Getting started

  1. Add the Dynoscale add-on: heroku addons:create dscale
  2. Install the agent: npm install dynoscale-node
  3. Mount the middleware first, before your routes.
  4. Deploy.

DYNOSCALE_URL is set by the add-on. The agent only reports from the dyno whose name ends in .1 (normally web.1).

const express = require("express");
const dynoscale = require("dynoscale-node");

const app = express();
app.use(dynoscale());

app.get("/", (req, res) => {
  res.send("Hello from Express, scaled by Dynoscale!");
});

app.listen(process.env.PORT || 3000);

The middleware is a (req, res, next) function, so the same call works on Connect. With the node:http module, pass the request through dynoscale() and call your handler from next. See examples/http/server.js.

const http = require("node:http");
const dynoscale = require("dynoscale-node");
const middleware = dynoscale();

http.createServer((req, res) => {
  middleware(req, res, () => {
    res.end("Hello from Node, scaled by Dynoscale!\n");
  });
}).listen(process.env.PORT || 3000);

Confirm the install on Heroku:

heroku run node -e "console.log(require('dynoscale-node').VERSION)"

What gets sent

On each request to the *.1 dyno the agent samples:

  • Web queue time, in whole seconds, from the Heroku X-Request-Start header (t=<epoch milliseconds> or a bare millisecond timestamp).
  • BullMQ queue latency, in milliseconds, for each configured queue. The source is bullmq:<queue>. This is read from Redis in the web process, the same way the Ruby agent reads Sidekiq and Resque.

Samples collect into one in-memory report. Five seconds after the first sample, a background loop POSTs the report as CSV to DYNOSCALE_URL:

timestamp,metric,source,metadata

timestamp is Unix seconds. After a successful publish the agent waits 30 seconds, or whatever config.publish_frequency the response contains. A failed publish is retried after 15 seconds. Published fields are the dyno name (X_DYNO), the app name (X_APP_NAME, from HEROKU_APP_NAME), and User-Agent: dynoscale-node;<version>.

A missing X-Request-Start skips that sample. The request still reaches your app.

BullMQ

Install BullMQ in the app (npm install bullmq). The adapter turns on when it can load bullmq and finds a Redis URL.

Name the queues in either place:

heroku config:set DYNOSCALE_BULLMQ_QUEUES=mail,pdf
app.use(dynoscale({
  bullmq: {
    queues: ["mail", "pdf"],
    connection: process.env.REDIS_URL,
  },
}));

With no names configured, the agent scans Redis for BullMQ meta keys using the first Redis URL it finds (REDIS_URL, REDIS_TLS_URL, and the Redis Cloud, Redis To Go, OpenRedis, and RedisGreen URL variables). DYNOSCALE_REDIS_URL overrides that search. Set bullmq.prefix when the queues do not use the default bull prefix.

Latency is the age of the oldest waiting job. Delayed jobs are not part of that wait list.

Environment

| Variable | Effect | | --- | --- | | DYNOSCALE_URL | Required. Publish target, set by the add-on. | | DYNO | Heroku dyno name. Reporting runs only when it ends in .1. | | HEROKU_APP_NAME | Sent as X_APP_NAME. Enable Heroku's runtime-dyno-metadata lab to set it. | | SKIP_DYNOSCALE_AGENT | Any value, including an empty one, turns the agent off. Use this on review, staging, and development apps. | | DYNOSCALE_DEV | Set to true to report even without DYNO. Queue time is simulated as 0–100 seconds, and publishes are not delayed. | | DYNOSCALE_BULLMQ_QUEUES | Comma-separated BullMQ queue names. | | DYNOSCALE_REDIS_URL | Redis URL for BullMQ, when it should not come from the provider URL. |

In a Node cluster (node:cluster, throng, and similar), only worker id 1 reports. A process that is not a cluster worker always reports. Pass isReportingProcess to replace that rule.

Shutdown

dynoscale.stop() ends the publish loop and closes BullMQ clients. The loop's timer does not keep the process alive on its own; your HTTP server does.

Development

npm test

Requires Node.js 18 or newer.