Providers & Failover

Providers & Failover Engine

NexoMailer is designed to be indestructible. By supporting multiple providers simultaneously, it ensures that your emails are delivered even if one service goes down.

Installation

Install the providers module via npm. This package contains the official wrappers for Resend, SES, and the abstract classes needed to build your own.

npm install @nexomailer/providers

(Alternatively, you can use pnpm add @nexomailer/providers or yarn add @nexomailer/providers).

Note: If you are only using native SMTP, you can use @nexomailer/smtp instead. See the SMTP Documentation.


Supported Providers

TypePackageKey Config Fields
smtp@nexomailer/smtphost, port, auth.user, auth.pass
resend@nexomailer/providersapiKey
ses@nexomailer/providersregion, accessKeyId, secretAccessKey

1. Sequential Failover (Recommended)

The sequential strategy (default) tries providers one by one based on their priority (1 is highest). This is perfect for setting up a cheap/primary provider with a reliable/expensive fallback.

import { NexoMailer } from '@nexomailer/core';
 
const mailer = new NexoMailer({
  // Tell the engine to use Priority-based failover
  failover: { strategy: 'sequential', maxRetries: 3 },
  
  providers: [
    // PRIMARY: NexoMailer will ALWAYS try Resend first
    { 
      type: 'resend', 
      priority: 1, 
      config: { apiKey: process.env.RESEND_API_KEY } 
    },
    
    // FALLBACK: If Resend API is down or returns a 5xx error, 
    // NexoMailer instantly switches to SMTP without throwing an error to your users
    { 
      type: 'smtp', 
      priority: 2, 
      config: { 
        host: 'smtp.gmail.com',
        port: 587,
        auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS }
      } 
    }
  ]
});

2. Weighted Load Balancing

If you have high volume, you can split traffic across providers to avoid hitting rate limits.

const mailer = new NexoMailer({
  // Tell the engine to split traffic instead of prioritizing
  failover: { strategy: 'weighted' },
  
  providers: [
    // 70% of all emails sent will be routed through AWS SES
    { 
      type: 'ses', 
      weight: 70, 
      config: { 
        region: 'us-east-1',
        accessKeyId: process.env.AWS_KEY,
        secretAccessKey: process.env.AWS_SECRET
      } 
    },
    
    // The remaining 30% will go through Resend
    { 
      type: 'resend', 
      weight: 30, 
      config: { apiKey: process.env.RESEND_API_KEY } 
    }
  ]
});

3. Registering Custom Providers

You can extend NexoMailer by adding your own provider engine (e.g., Postmark, SendGrid).

Step 1: Create the Provider Class

import { EmailProvider } from '@nexomailer/providers';
 
// 1. Extend the base class
class PostmarkProvider extends EmailProvider {
  // 2. Implement the required 'send' method
  async send(options) {
    // 3. Translate NexoMailer options to Postmark API format
    const payload = {
      From: options.from,
      To: options.to,
      Subject: options.subject,
      HtmlBody: options.html
    };
    
    // Call Postmark API (pseudo-code)
    const result = await postmarkClient.sendEmail(payload);
    
    // 4. Return the standard NexoMailer response format
    return { 
      id: result.MessageID, 
      status: 'sent' 
    };
  }
}

Step 2: Register it with NexoMailer

import { defaultRegistry } from '@nexomailer/providers';
 
// 1. Add it to the global registry BEFORE initializing NexoMailer
defaultRegistry.register('postmark', PostmarkProvider);
 
// 2. Now you can use 'postmark' as a valid type!
const mailer = new NexoMailer({
  providers: [{ type: 'postmark', config: { apiKey: '...' } }]
});

Health Checks

NexoMailer keeps track of provider health. If a provider consistently fails, it is marked as "Inactive" for a cooldown period.

[!TIP] Check Provider Status: You can inspect the health of your infrastructure at runtime to build custom admin dashboards:

const health = await mailer.getHealth();
console.log(health.providers); 
// Example Output: [{ type: 'resend', status: 'active' }, { type: 'smtp', status: 'cooldown' }]