Getting Started
Install @adonis-agora/resilience, wrap a flaky call with a composed policy, then register named policies in config and reach them through the container.
Getting @adonis-agora/resilience running is three steps: install the package, compose a policy, and (optionally) register named policies in config/resilience.ts so you can reach them through the container-resolved ResilienceService. You can use the policies entirely standalone — the AdonisJS surfaces are a convenience, not a requirement.
Prerequisites
- Node.js 20.6+
- AdonisJS 7 (
@adonisjs/core ^7.3.0) - TypeScript 5+
Install
node ace add @adonis-agora/resiliencenode ace add installs the package, runs node ace configure @adonis-agora/resilience for you (registering the provider), and publishes config/resilience.ts. To configure an already-installed package, run the configure step directly:
node ace configure @adonis-agora/resilienceThis registers @adonis-agora/resilience/resilience_provider in adonisrc.ts and writes config/resilience.ts. @adonis-agora/diagnostics and @adonis-agora/context are optional — install them only if you want diagnostics emission or tenant-aware breaker keys (see Integrations).
Wrap a call with a policy
Every policy exposes execute(op). Compose several with wrap() — outermost first — and run your operation inside:
import { wrap, timeout, retry, exponential, circuitBreaker, InMemoryResilienceStore } from '@adonis-agora/resilience'
const store = new InMemoryResilienceStore()
const charge = wrap(
timeout(2_000), // give up after 2s
retry({ attempts: 3, backoff: exponential(100) }), // up to 3 tries, 100ms → 200ms
circuitBreaker({ key: 'payments', store, threshold: 5, cooldownMs: 30_000 }),
)
const result = await charge.execute(() => chargeCard(order))Your operation receives a PolicyContext ({ signal, attempt }) if you want it — wire the AbortSignal into fetch/your client to make timeouts actually cancel work:
await charge.execute(({ signal }) => fetch(url, { signal }))Register named policies (optional)
config/resilience.ts (published by configure) is where you register reusable, named policies and pick a store. Uncomment and adapt:
import { defineConfig, stores, wrap, timeout, retry, exponential } from '@adonis-agora/resilience'
export default defineConfig({
// The circuit-breaker store. `memory` is in-process; see Stores for Lucid / Redis.
default: 'memory',
stores: {
memory: stores.memory(),
},
// Emit diagnostics events on `agora:resilience:*`. Default true.
// emit: true,
// Named, reusable policies resolvable via `resilience.execute('payments', op)`.
policies: {
payments: () => wrap(timeout(2_000), retry({ attempts: 3, backoff: exponential(100) })),
},
})The provider binds a singleton ResilienceService built lazily from this config. Import the ready-to-use singleton from @adonis-agora/resilience/services/main into a service and run the named policy around the outbound call:
import resilience from '@adonis-agora/resilience/services/main'
import type Order from '#models/order'
export default class PaymentGatewayService {
async charge(order: Order) {
// the named `payments` policy wraps the call to the payment gateway
return resilience.execute('payments', ({ signal }) =>
fetch('https://api.stripe.com/v1/charges', {
method: 'POST',
body: JSON.stringify({ amount: order.total, currency: 'usd' }),
signal, // thread the abort signal so the 2s timeout can cancel the request
}).then((res) => res.json())
)
}
}By default the service uses the in-memory store and emits diagnostics events. To share circuit state across instances, point default at a Lucid or Redis store built with the stores factory — see Stores. To turn emission off, pass emit: false.
Where to go next
Policies
timeout, retry, circuit breaker, wrap and failover in depth — plus the typed errors.
Service & config
config/resilience.ts, the provider, and the ResilienceService API.
Stores
Pick a Lucid / Redis store in config, plus the ResilienceStore contract.
Testing
Drive time deterministically with FakeClock; validate a custom store.
Resilience
Composable resilience policies for AdonisJS — timeout, retry, circuit breaker and failover, with a pluggable, distributed circuit-breaker store.
Policies
The policy engine — timeout, retry with backoff, circuit breaker, wrap composition, and the list-oriented failover primitive, plus the typed errors they throw.