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

@workkit/ratelimit

v0.2.0

Published

Rate limiting primitives for Cloudflare Workers — fixed window, sliding window, and token bucket algorithms

Readme

@workkit/ratelimit

KV-backed rate limiting with fixed window, sliding window, and token bucket algorithms

npm bundle size

Install

bun add @workkit/ratelimit

Usage

Before (manual rate limiting)

// DIY rate limiting with KV — error-prone, no standard headers
const key = `rl:${ip}:${Math.floor(Date.now() / 60000)}`
const count = parseInt((await env.RL_KV.get(key)) ?? "0")
if (count >= 100) {
  return new Response("Too many requests", { status: 429 })
}
await env.RL_KV.put(key, String(count + 1), { expirationTtl: 120 })

After (workkit ratelimit)

import { fixedWindow, slidingWindow, tokenBucket, rateLimitHeaders } from "@workkit/ratelimit"

// Fixed window — simple and efficient
const limiter = fixedWindow({
  namespace: env.RATE_LIMIT_KV,
  limit: 100,
  window: "1m",
})

const result = await limiter.check(`user:${userId}`)
if (!result.allowed) {
  return new Response("Too many requests", {
    status: 429,
    headers: rateLimitHeaders(result), // X-RateLimit-Limit, Remaining, Reset
  })
}

// Sliding window — smoother distribution
const slidingLimiter = slidingWindow({
  namespace: env.RATE_LIMIT_KV,
  limit: 1000,
  window: "1h",
})

// Token bucket — burst-friendly
const bucketLimiter = tokenBucket({
  namespace: env.RATE_LIMIT_KV,
  capacity: 50,
  refillRate: 10,
  refillInterval: "1m",
})

API

Rate Limiters

  • fixedWindow(options) — Fixed window counter. Options: namespace, limit, window, prefix?
  • slidingWindow(options) — Sliding window counter for smoother rate limiting
  • tokenBucket(options) — Token bucket with configurable refill rate and burst capacity
  • composite(limiters) — Combine multiple limiters (all must allow)

Each returns a RateLimiter with:

  • .check(key) — Returns { allowed, remaining, resetAt, limit }

Utilities

  • rateLimitHeaders(result) — Generate standard X-RateLimit-* headers
  • rateLimitResponse(result) — Generate a 429 Response with headers
  • parseDuration(str) — Parse "1m", "1h", "30s" to milliseconds

Tiered Rate Limiting

  • tiered(options) — Create a tiered rate limiter with per-plan limits. Each tier gets its own limit and underlying limiter instance. Tiers with Number.POSITIVE_INFINITY short-circuit without touching KV. Supports "fixed" (default) or "sliding" algorithm.
    • .check(key, tier) — Check rate limit for a key at a specific tier
    • .forTier(tier) — Get a standalone RateLimiter bound to a tier
import { tiered } from "@workkit/ratelimit"

const limiter = tiered({
  namespace: env.RATE_LIMIT_KV,
  tiers: { free: { limit: 100 }, pro: { limit: 10000 }, enterprise: { limit: Infinity } },
  window: "1h",
  defaultTier: "free",
})
const result = await limiter.check(`user:${userId}`, userPlan) // "free" | "pro" | "enterprise"

Quota Buckets

  • quota(options) — Calendar-aligned usage tracking with multiple concurrent windows. Requests are only counted if ALL windows allow them. Supports variable cost per request.
    • .check(key, cost?) — Check and consume quota (cost defaults to 1). Returns { allowed, remaining, resetAt, limit, quotas }.
    • .usage(key) — Read-only usage query across all windows
import { quota } from "@workkit/ratelimit"

const q = quota({
  namespace: env.RATE_LIMIT_KV,
  limits: [
    { window: "1h", limit: 100 },
    { window: "1d", limit: 1000 },
  ],
})
const result = await q.check("user:123", 5) // cost of 5 units
const usage = await q.usage("user:123")      // read-only, no consumption

License

MIT