Failover
Continue with a fallback adapter when a retryable provider failure occurs.
import { createPostbote } from "@postbote/core";
import { postmark } from "@postbote/adapter-postmark";
import { failover } from "@postbote/plugin-failover";
import { resend } from "@postbote/adapter-resend";
const resilience = failover({
fallbacks: [postmark({ serverToken: process.env.POSTMARK_SERVER_TOKEN! })],
onFailover: ({ from, to, error }) => {
logger.warn({ from, to, code: error.code }, "mail provider failed over");
},
});
const mailer = createPostbote({
adapter: resend({ apiKey: process.env.RESEND_API_KEY! }),
plugins: [resilience],
});The single-adapter pattern accepts fallback instances. The multiple-adapter pattern registers every adapter once and accepts only registered names for adapter and string fallback keys. Literal names are type-checked, and duplicate registry names are rejected.
The primary adapter is always attempted first, followed by fallbacks in order. By default, failover continues only when error.retryable is true. Invalid messages, rejected recipients, and authentication failures never trigger a fallback.
When every candidate fails, Postbote throws FailoverExhaustedError. Its attempts array records each adapter and its failure.
Failover does not retry an adapter. If you add your own retry middleware, compose it deliberately: outer plugins observe one logical send, while plugins inside failover run once per attempt.