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

@kfunk-load/cli

v1.1.1

Published

Distributed load testing tool

Readme

kFunk CLI

Distributed load testing tool. Stress-test any system with custom scripts and get detailed latency metrics.

Install

npm install -g @kfunk-load/cli

Quick Start

Create a test script:

// my-test.js
export default {
  async setup(ctx) {
    ctx.state.url = "https://api.example.com/health"
  },

  async run(ctx, metrics) {
    await metrics.measure("http_get", async () => {
      const res = await fetch(ctx.state.url)
      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      await res.json()
    })
    metrics.increment("requests")
  },

  async teardown(ctx) {
    // clean up resources
  },
}

Run it:

kfunk run my-test.js --vus 10 --duration 30

Test Script Format

A test script exports an object with lifecycle hooks:

| Hook | Required | Description | |------|----------|-------------| | setup(ctx) | No | Initialize state, open connections, prepare data | | run(ctx, metrics) | Yes | Main test loop — called repeatedly for the duration | | teardown(ctx) | No | Clean up resources |

Context (ctx)

| Property | Type | Description | |----------|------|-------------| | ctx.vuId | number | Virtual user ID (0-based) | | ctx.totalVUs | number | Total number of VUs in this run | | ctx.state | object | Persistent state bag for the VU |

Metrics API

The metrics object passed to run():

| Method | Description | |--------|-------------| | metrics.measure(name, fn) | Time an async function and record duration | | metrics.startTimer() | Start a manual timer (returns timestamp) | | metrics.record(name, startTime) | Record duration since startTime | | metrics.increment(name, value?) | Increment a counter (default 1) |

CLI Options

kfunk run <script>

| Option | Description | Default | |--------|-------------|---------| | --vus <n> | Number of virtual users (or VUs per worker in distributed mode) | 10 | | --duration <s> | Test duration in seconds | 30 | | --stagger <ms> | Delay between spawning each VU | 0 | | --service-url <url> | Worker URL (enables distributed mode without an infra plugin) | — | | --workers <n> | Number of workers (distributed only) | 1 | | --worker-stagger <ms> | Delay between launching each worker | 0 | | --config <path> | Path to kfunk config file | auto-detected | | --json | Output raw JSON | false |

kfunk deploy

Deploy workers using an infrastructure plugin, or fall back to the legacy scripts/deploy.sh script.

kfunk deploy

If no infra plugin is configured, the deploy command falls back to the legacy GCP Cloud Run deploy script:

| Environment Variable | Description | Default | |---------------------|-------------|---------| | KFUNK_REGION | GCP region to deploy to | us-central1 | | KFUNK_SERVICE_NAME | Cloud Run service name | kfunk-worker |

Examples

HTTP Load Test

// example-test.js
export default {
  async setup(ctx) {
    ctx.state.url = "https://jsonplaceholder.typicode.com/posts/1"
  },

  async run(ctx, metrics) {
    await metrics.measure("http_get", async () => {
      const res = await fetch(ctx.state.url)
      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      await res.json()
    })
    metrics.increment("requests")
  },
}
kfunk run example-test.js --vus 5 --duration 10

NoLag Broker Test

// example-nolag.js
import { NoLag } from "@nolag/js-sdk"

const TOKEN = process.env.NOLAG_TOKEN
const TOPIC = process.env.NOLAG_TOPIC || "kfunk/load-test/messages"

export default {
  async setup(ctx) {
    if (!TOKEN) throw new Error("NOLAG_TOKEN env var is required")
    const client = NoLag(TOKEN, { qos: 1, reconnect: false })
    await client.connect()
    ctx.state.client = client
    ctx.state.seq = 0
    ctx.state.pending = new Map()

    client.subscribe(TOPIC)
    client.on(TOPIC, (data) => {
      if (data._vuId === ctx.vuId) {
        const sent = ctx.state.pending.get(data._seq)
        if (sent) {
          ctx.state.lastRoundtrip = performance.now() - sent
          ctx.state.pending.delete(data._seq)
        }
      }
    })
  },

  async run(ctx, metrics) {
    const seq = ctx.state.seq++
    ctx.state.pending.set(seq, performance.now())

    await metrics.measure("publish", async () => {
      ctx.state.client.emit(TOPIC, {
        _vuId: ctx.vuId, _seq: seq, text: "kfunk"
      }, { echo: true })
    })
    metrics.increment("messages_sent")

    await new Promise(r => setTimeout(r, 100))

    if (ctx.state.lastRoundtrip !== undefined) {
      metrics.record("roundtrip", ctx.state.lastRoundtrip)
      metrics.increment("messages_received")
      ctx.state.lastRoundtrip = undefined
    }
  },

  async teardown(ctx) {
    ctx.state.client?.disconnect()
  },
}
NOLAG_TOKEN=your_token kfunk run example-nolag.js --vus 10 --duration 30

Plugin System

kFunk supports plugins to extend its functionality. There are two plugin types:

  • Event plugins stream test lifecycle events in real-time (from both the CLI and distributed workers)
  • Infrastructure plugins manage distributed workers on any cloud provider

Configuration

Create a kfunk.config.js file in your project root:

// kfunk.config.js
export default {
  plugins: [
    "@kfunk-load/plugin-gcp",
    { name: "@kfunk-load/plugin-nolag", config: { apiKey: process.env.NOLAG_KEY } },
  ],
  infra: "@kfunk-load/plugin-gcp",
  "@kfunk-load/plugin-gcp": {
    region: "us-central1",
    serviceName: "kfunk-worker",
  },
}
  • plugins — list of plugin package names, or { name, config } objects for inline config
  • infra — which plugin to use for infrastructure (must be listed in plugins)
  • Top-level keys matching a plugin name provide plugin-specific configuration

No config file is required — without one, kFunk runs tests locally with no plugins.

Event Plugins

Event plugins observe the test lifecycle. Their hooks fire on the CLI and inside distributed workers:

| Hook | Where | Description | |------|-------|-------------| | onTestStart(context) | CLI | Test is starting | | onVUStart(vuId, totalVUs) | CLI + Workers | A VU is about to start | | onVUComplete(vuMetrics) | CLI + Workers | A VU finished | | onProgress(message) | CLI | Progress update | | onTestEnd(context, results) | CLI | Test complete with aggregated results |

In distributed mode, event plugin configs are serialized and sent to workers. Workers load the event plugins locally and fire onVUStart/onVUComplete hooks in real-time during VU execution. This means the event plugin npm packages must be installed on the worker image — the infra plugin's deploy() handles this automatically.

Infrastructure Plugins

Infrastructure plugins manage distributed workers on any cloud:

| Method | Description | |--------|-------------| | deploy(options) | Deploy workers (builds image with event plugin deps), returns { serviceUrl } | | runDistributed(options) | Run a distributed test, returns RuntimeResult | | getAuthHeaders(serviceUrl) | Get auth headers for worker requests | | teardown(options) | Destroy deployed workers |

When an infra plugin is configured, kfunk deploy delegates to it and kfunk run uses it for distributed execution automatically (no --service-url needed).

Writing a Plugin

A plugin package exports a factory function as its default export:

// Event plugin example
export default function(config) {
  return {
    name: "my-event-plugin",
    type: "event",
    async onTestStart(context) { /* ... */ },
    async onVUComplete(vuMetrics) { /* ... */ },
    async onTestEnd(context, results) { /* ... */ },
    async destroy() { /* cleanup */ },
  }
}
// Infrastructure plugin example
export default function(config) {
  return {
    name: "my-infra-plugin",
    type: "infra",
    async deploy(options) { /* ... */ return { serviceUrl } },
    async runDistributed(options) { /* ... */ return runtimeResult },
    async getAuthHeaders(serviceUrl) { /* ... */ return headers },
    async destroy() { /* cleanup */ },
  }
}

Available Plugins

| Package | Type | Description | |---------|------|-------------| | @kfunk-load/plugin-gcp | Infrastructure | Deploy and run distributed tests on Google Cloud Run | | @kfunk-load/plugin-nolag | Event | Stream test events to a NoLag real-time broker |

Distributed Testing with Plugins

With an infra plugin configured, distributed testing is seamless:

# Deploy workers (infra plugin builds the image and deploys)
kfunk deploy

# Run distributed — no --service-url needed, the plugin handles it
kfunk run my-test.js --workers 10 --vus 20 --duration 60

Distributed Test with GCP Cloud Run (Legacy)

You can also use --service-url directly without an infra plugin. This uses the legacy orchestrator (no automatic auth — workers must be publicly accessible or you must handle auth separately).

Prerequisites

  1. Install the Google Cloud CLI
  2. Authenticate and set your project:
gcloud auth login
gcloud config set project YOUR_PROJECT_ID
  1. Enable the required APIs:
gcloud services enable run.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com

Deploy & Run

  1. Deploy the worker to Cloud Run:

    kfunk deploy
  2. Run a distributed test using the service URL printed by deploy:

    kfunk run my-test.js \
      --service-url https://kfunk-worker-xxxxx.run.app \
      --workers 10 \
      --duration 30

Output

kFunk outputs a summary table with:

  • Latency stats: min, avg, median, p90, p95, p99, max
  • Counter totals
  • VU count, total iterations, and duration

Use --json for machine-readable output in CI/CD pipelines.

Using Custom Packages

Your test scripts can import any npm package. Install them in your project directory:

npm install @nolag/js-sdk
kfunk run example-nolag.js --vus 10 --duration 30

kFunk resolves packages from your project's node_modules.

License

MIT