PUBLIC BETA NODE.JS & LLM OPEN SOURCE MIT LICENSE TYPESCRIPT

Build resilient Node.js and LLM applications. One composable TypeScript API.

Compose retry, timeout, circuit breaking, bulkheads, rate limiting, fallback, cache, deduplication, and hedging into one predictable pipeline — then put that same pipeline in front of LLM generation and streaming, with provider adapters, budget protection, typed events, and metrics.

Public Beta 1 — APIs may still change before the stable release.

SIMPLIFIED REQUEST PATH

INPUT Request
RESILI PIPELINE
Failure Recovery
Retry · Fallback · Breaker
Latency Control
Timeout · Hedging
Load Protection
Rate Limiter · Bulkhead
Request Management
Cache · Deduplication
TARGET OPERATION
Response
Typed Result
641 Automated Tests
9 Built-in Core Policies
8 Published Packages
3 HTTP Adapters
3 LLM Provider Adapters
MIT License

Why developers choose Resili

Resili brings reliability controls, request optimization, cancellation, and observability into one typed execution model.

One composable API

A policy wraps an async function, not a request object — so the same configuration protects an HTTP call, a database query, an SDK call, or an LLM generation.

TypeScript-first

Operation arguments and result types flow through the client. Invalid configuration throws at build time rather than degrading silently.

Predictable policy ordering

Built-in policies execute through a defined canonical pipeline, and ordering is configurable with relative anchors.

Native cancellation primitives

Cancellation is a standard AbortSignal. In a core execution the caller signal and per-attempt timeouts compose into the one signal your operation receives.

Observable and private

Typed events and metric instruments expose policy and LLM behaviour. No outbound telemetry, and no prompts, generated text, or credentials in any payload.

Lightweight core

@resili/core has zero runtime dependencies. Transport and vendor code stays in adapter packages you opt into.

Production failures are the ones you didn't plan for.

Every service reimplements retry logic. Every team learns the hard way about cascade failures, thundering herds, and cascading timeouts. LLM providers add rate limits, long tail latency, and a bill that grows with every retry. The result is inconsistency, incidents, and engineering hours spent on undifferentiated work.

Scattered retry logic

Copy-pasted across every service, with subtle differences that cause production incidents.

Cascade failures

One slow dependency brings down the entire system when there's no circuit breaker.

Thundering herds

Retries overwhelm a recovering service. No bulkheads, no rate limits, no deduplication.

Zero observability

You find out about resilience issues — and about what a retry loop cost you — through user reports, not typed events or metrics.

Fluent. Typed.
Predictable.

Resili applies policies through a predictable canonical pipeline. Every execution is typed, every event is observable, and every policy boundary is explicit.

  • Full TypeScript generics — result types flow through the entire pipeline
  • Core executions compose a caller signal with each attempt timeout
  • Typed lifecycle events for retries, circuit state changes, and cache hits
  • Thin wrappers for Fetch, Axios, and Undici — caller AbortSignal composes with timeout and retry
  • Custom policies and plugins through definePolicy and definePlugin

Caller AbortSignal cancellation composes with Resili timeout and retry behavior across Fetch, Axios, and Undici. LLM provider adapters also forward a caller signal to the SDK.

payment.service.ts
import { resili } from "@resili/core";

const payments = resili(async (paymentId: string) => {
  const response = await fetch(
    `https://api.example.com/payments/${paymentId}`
  );

  if (!response.ok) {
    throw new Error(`Request failed: ${response.status}`);
  }

  return response.json() as Promise<{
    id: string;
    status: string;
  }>;
})
  .cache({
    key: (paymentId) => paymentId,
    ttl: 5_000,
  })
  .retry({
    maxAttempts: 3,
    backoff: "exponential",
    jitter: "none",
  })
  .circuitBreaker({
    minimumThroughput: 10,
  })
  .timeout({
    perAttemptMs: 1_000,
  })
  .dedupe({
    key: (paymentId) => paymentId,
  })
  .hedge({
    delay: 150,
  })
  .build();

const payment = await payments.call("payment-42");

Predictable Order of Execution

Resili executes policies in a deterministic order across all client wrappers to protect local and downstream resources safely. Only the policies you configure are installed. With @resili/llm, Budget Guard registers just before retry, so one reservation covers the whole logical request.

1 Fallback
2 Cache
3 Retry
4 Circuit Breaker
5 Timeout
6 Deduplication
7 Hedged Requests
8 Rate Limiter
9 Bulkhead
10 Target Operation

Built for asynchronous Node.js workloads

External APIs
Database calls
SDK calls
Queue operations
Background jobs
Internal services
LLM API calls
AI agent steps

Every resilience pattern, ready to compose.

Nine policies that compose into a single deterministic execution pipeline. A policy is installed only when you configure it, and the same nine protect a fetch call, an SDK call, a queue publish, or an LLM generation. No magic, no surprises.

Retry

Retry transient failures with bounded attempts and configurable backoff.

Core Policy

Timeout

Give each attempt a strict time budget through AbortSignal-aware cancellation.

Core Policy

Circuit Breaker

Stop repeatedly calling an unhealthy dependency and probe its recovery.

Core Policy

Bulkhead

Limit concurrent executions and queue depth to protect local resources.

Core Policy

Rate Limiter

Control request throughput using token-bucket or sliding-window strategies.

Core Policy

Fallback

Return an alternative result when configured failures reach the fallback boundary.

Core Policy

Hedged Requests

Start one delayed backup execution to reduce long-tail latency for safe operations.

Request Management

Request Deduplication

Share one in-flight execution across concurrent callers with the same key.

Request Management

Memory Cache

Store successful results in a bounded per-client cache with configurable TTL.

Request Management

Resilience for LLM workloads.

Bring retries, timeouts, streaming, usage tracking, and budget control to OpenAI, Anthropic, and Google Gemini through the same Resili execution model. Public Beta — @resili/llm performs no network I/O and never constructs a vendor client. You own the SDK and the credentials.

LLM REQUEST PATH

APPLICATION Your app
@RESILI/LLM
Resilience
Retry · Timeout
Streaming
Pull-through · Commit point
Cost Control
Budget Guard · Usage
Then the adapter
OpenAI · Anthropic · Gemini
PROVIDER SDK
Your client
OpenAI Anthropic Gemini

Streaming

Pull-through streaming with consumer-driven backpressure. Retry is allowed before the first delivered non-empty text delta. After visible text has committed, Resili does not start another provider generation.

stream()

Safe retries

Provider SDK retries are disabled so Resili owns retry behaviour. OpenAI and Anthropic use maxRetries: 0. Gemini uses HTTP attempts: 1.

Resilience

Budget Guard

Estimated cost is reserved before execution and settled against provider-reported usage. Pricing is caller-supplied. Accounting is process-local — not distributed.

Cost Control

Usage & cost

Provider token counts are normalized to input, output, and total. Cost is calculated in integer micro-USD when you supply a price table. Resili hard-codes no vendor prices.

Cost Control

Timeouts & cancellation

A per-attempt timeout covers the full streaming attempt, including time between pulls. Before commit, a timeout may retry. After commit, no second generation is started — the error is classification: "timeout", retryable: false. A caller AbortSignal reaches the provider SDK; cancellation never retries.

Resilience

Observability

Typed LlmStreamStarted, LlmStreamCompleted, and LlmStreamFailed events. Prompts, completions, and raw chunks are never placed on the event bus or in metrics.

Telemetry

Three adapters. You construct the client.

Each adapter maps a vendor SDK you already own onto generate() and stream(). No Responses API, tools, multimodal APIs, or distributed budgets in this beta.

OpenAI

@resili/llm-openai · 0.1.0-beta.1. Chat Completions, generate() and stream(), usage mapping, and AbortSignal into the SDK. maxRetries: 0.

Adapter

Anthropic

@resili/llm-anthropic · 0.1.0-beta.1. Messages API, generate() and stream(), partial streaming usage merge, and AbortSignal into the SDK. maxRetries: 0.

Adapter

Google Gemini

@resili/llm-gemini · 0.1.0-beta.1. generateContent and generateContentStream via @google/genai, usage mapping, abortSignal, and cumulative snapshot de-duplication. HTTP attempts: 1.

Adapter

One stream,
one generation.

Retries may occur before the first non-empty text delta is delivered to your loop. Once visible text has been committed to the consumer, Resili will not start another provider generation for a retryable failure or a timeout — so a stream is never two answers concatenated into one.

  • Retries only before the first non-empty text delta is delivered
  • After delivery, no second provider generation is started
  • A post-commit timeout surfaces as a non-retryable LLM timeout error
  • Cancellation never retries, before or after that point
  • One budget reservation per request, settled against actual usage

Behaviour shipped in @resili/llm 0.1.0-beta.1. Read the streaming guide for the full retry and timeout matrix.

assistant.stream.ts
import OpenAI from "openai";
import { createLlmClient } from "@resili/llm";
import { createOpenAiProvider } from "@resili/llm-openai";

const llm = createLlmClient({
  provider: createOpenAiProvider({
    client: new OpenAI(),
  }),
  model: "gpt-4.1-mini",
  timeout: { perAttemptMs: 60_000 },
  retry: {
    maxAttempts: 3,
    backoff: "exponential",
    baseDelayMs: 500,
    jitter: "none",
  },
});

const stream = llm.stream({
  input: "Explain backpressure in one sentence.",
});

for await (const event of stream) {
  if (event.type === "text-delta") {
    process.stdout.write(event.text);
  }
}

// Usage after the stream closes. Cost is present if a price table was configured.
const { usage, cost } = await stream.result();

Built as a monorepo.
Ship only what you need.

Eight npm packages across two independently versioned lines. Core and HTTP are at 0.2.0-beta.1; the LLM line is at 0.1.0-beta.1. Plain npm install resolves to Beta 1 on latest; the @beta tag is also available. Historical @alpha builds remain published.

@resili/core 0.2.0-beta.1

Core Runtime

Context, pipeline, the nine policies, typed events, metrics contracts, errors, and plugins. Zero runtime dependencies.

npm install @resili/core
@resili/fetch 0.2.0-beta.1

Fetch Adapter

Thin fetch-compatible wrapper. Defaults to globalThis.fetch and returns the raw Response.

npm install @resili/core @resili/fetch
@resili/axios 0.2.0-beta.1

Axios Adapter

Axios-compatible wrapper over an implementation you inject, so the instance and its version stay yours. No peer dependency — install axios only if your code imports it.

npm install @resili/core @resili/axios axios
@resili/undici 0.2.0-beta.1

Undici Adapter

Undici-compatible request wrapper over an injected implementation, for lower-level control. No peer dependency — install undici only if your code imports it.

npm install @resili/core @resili/undici undici
@resili/llm 0.1.0-beta.1

LLM Runtime

Provider-neutral client with generate() and stream(), usage normalization, pricing, Budget Guard, and telemetry.

npm install @resili/core @resili/llm
@resili/llm-openai 0.1.0-beta.1

OpenAI Adapter

OpenAI Chat Completions, unary and streaming. Optional peer on openai; you construct the client.

npm install @resili/llm-openai openai
@resili/llm-anthropic 0.1.0-beta.1

Anthropic Adapter

Anthropic Messages, unary and streaming, with partial usage merging. Optional peer on @anthropic-ai/sdk.

npm install @resili/llm-anthropic @anthropic-ai/sdk
@resili/llm-gemini 0.1.0-beta.1

Gemini Adapter

Google Gemini generateContent and generateContentStream via @google/genai, with cumulative snapshot de-duplication.

npm install @resili/llm-gemini @google/genai

Quality is the foundation, not an afterthought.

Releases are cut from main only after linting, formatting, strict TypeScript checks, the full test suite, workspace builds, and the API report check pass — then verified against the public npm registry in a clean consumer project.

641 automated tests
Strict TypeScript
ESLint
Prettier
Workspace builds
API Extractor
Package tarball validation
Benchmark framework
GitHub Actions CI
641 Automated Tests
0 Core Runtime Deps
8 npm Packages
MIT Open Source License

Where the project is today

Two independently versioned lines. Public Alpha is historical; Beta 1 is current on latest and beta. Stable is not scheduled — no date.

NOW

Public Beta 1

  • Nine core policies and HTTP adapters with caller cancellation
  • LLM foundation, OpenAI, Anthropic, Gemini
  • Pull-through streaming and Budget Guard
  • 641 tests, Node 20 & 22, ESM and CommonJS
  • Primary APIs reviewed for Beta freeze — still may change before stable
NEXT

Toward stable

  • Further beta hardening
  • Real-world feedback and interaction testing
  • Documentation and compatibility review
  • TTFB / idle timeout exploration
  • Under consideration — none committed
LATER

Stable v1.0

  • Stable public API
  • Compatibility guarantees
  • Production-readiness criteria
  • No date, and no version between here and there is scheduled

Stop rewriting resilience logic. Start shipping.

Install the public beta for Node.js services or LLM workloads, try it on a non-critical path, and help shape what comes next.

npm install @resili/core

Building with LLMs? Install npm install @resili/core @resili/llm @resili/llm-openai openai — installation guide →

Public Beta 1 — APIs may still change before the stable release. Plain npm install resolves to Beta 1; @beta is also available.