npm package: @gilangjavier/headerbackoff
Description: Parse Retry-After and rate limit headers into deterministic retry plans.
Author: Gilang Javier
Latest version: 0.1.0

# headerbackoff

Parse `Retry-After` and common rate-limit headers into a deterministic retry plan.

`headerbackoff` helps you turn noisy HTTP throttling responses into one simple answer: **how long should I wait, and how fast can I keep sending requests?**

## Why this exists

Different APIs expose rate limits differently:

- `Retry-After`
- `RateLimit-Remaining`
- `RateLimit-Reset`
- `X-RateLimit-*`

Most teams end up re-implementing the same parsing logic in queue workers, cron jobs, scripts, and SDK wrappers.

`headerbackoff` gives you a tiny library and CLI for that job.

## Install

```bash
npm i @gilangjavier/headerbackoff
```

Or run it directly:

```bash
npx @gilangjavier/headerbackoff inspect --header "Retry-After: 17"
```

## CLI usage

```bash
headerbackoff inspect [--header "Key: Value"]... \
  [--headers-file headers.json] \
  [--stdin] \
  [--format text|json] \
  [--buffer-ms 0] \
  [--fallback-wait-ms 1000]
```

### Example: 429 with `Retry-After`

```bash
headerbackoff inspect --header "Retry-After: 17"
```

### Example: reset-window throttling

```bash
headerbackoff inspect \
  --header "RateLimit-Remaining: 0" \
  --header "RateLimit-Reset: 42" \
  --format json
```

### Example: inspect a captured header blob

```bash
cat response-headers.txt | headerbackoff inspect --stdin
```

## Library API

```ts
import { createBackoffPlan, parseRateLimitHeaders } from "@gilangjavier/headerbackoff";

const snapshot = parseRateLimitHeaders({
  "Retry-After": "12",
  "RateLimit-Remaining": "0",
  "RateLimit-Reset": "15",
});

const plan = createBackoffPlan(snapshot.raw, { bufferMs: 250 });

console.log(plan.waitMs); // 15250
console.log(plan.reason); // rate-limit-reset
```

## For agents

- Use `--format json` so your workflow can read `waitMs`, `reason`, `retryAt`, and `minSpacingMs`.
- If `waitMs > 0`, pause that worker or queue until `retryAt`.
- If `minSpacingMs` is present, you can spread remaining requests more evenly across the reset window.

Example:

```bash
headerbackoff inspect \
  --header "RateLimit-Remaining: 3" \
  --header "RateLimit-Reset: 9" \
  --format json
```

## For humans

- Drop this into shell scripts, queue workers, or custom SDK wrappers.
- Prefer feeding real response headers into `inspect` instead of hardcoding wait rules per provider.
- Add a small `--buffer-ms` if the provider's reset windows are a bit optimistic.

Example:

```bash
headerbackoff inspect \
  --header "Retry-After: Wed, 18 Mar 2026 03:00:10 GMT" \
  --buffer-ms 250
```

## Output fields

- `waitMs`: recommended wait before the next request
- `retryAt`: ISO timestamp for the next safe retry
- `reason`: why the wait was chosen (`retry-after`, `rate-limit-reset`, `remaining-zero`, or `none`)
- `limited`: whether the current response indicates you should back off
- `minSpacingMs`: suggested minimum spacing between remaining calls in the current window

## GitHub Actions example

```yaml
- name: Inspect throttled response headers
  run: |
    npx @gilangjavier/headerbackoff inspect \
      --header "RateLimit-Remaining: 0" \
      --header "RateLimit-Reset: 30" \
      --format json
```

## License

MIT