valve_

Quickstart

Create a valve, queue calls through it, and shut it down cleanly.

This page uses the default in-memory store, so you can run it without Redis. To share a budget between processes, finish here and then follow Share a quota across workers.

Before you begin

Install valve in a Node.js 20+ project with ESM enabled.

Create a valve

A valve is a named budget plus a local queue. This one allows 5 calls per second and at most 2 running at once.

quickstart.ts
import { createValve } from 'valvejs';

const github = createValve({
  id: 'github:my-script',
  rate: { limit: 5, interval: '1s' },
  concurrency: 2,
});

Queue work with run

run queues a function and resolves with its result. Types are preserved.

quickstart.ts
const users = ['octocat', 'torvalds', 'gaearon'];

const profiles = await Promise.all(
  users.map((name) =>
    github.run(async ({ signal }) => {
      const res = await fetch(`https://api.github.com/users/${name}`, {
        signal,
      });
      return (await res.json()) as { login: string; public_repos: number };
    }),
  ),
);

console.log(profiles.map((p) => `${p.login}: ${p.public_repos}`));

With the default burst: 1, starts are spaced evenly: one every 200ms.

Or wrap fetch

wrapFetch returns a drop-in fetch that goes through the valve, reads rate limit headers from every response, and retries 429s after the pause ends for GET, HEAD, OPTIONS, PUT and DELETE. POST and PATCH require an explicit opt-in; see Requests with side effects.

quickstart.ts
const githubFetch = github.wrapFetch();
const res = await githubFetch('https://api.github.com/rate_limit');

Close the valve

close stops accepting work and waits for running jobs. Pass drain: true to also run everything still queued.

quickstart.ts
await github.close({ drain: true });

Run it

npx tsx quickstart.ts

What you learned

  • A valve is identified by id. Valves with the same id and the same store share one budget.
  • The default store is a new private memory store per valve. Separate valves share nothing until you give them the same store instance.
  • run and wrapFetch queue work; close shuts the valve down.

Next steps

On this page