Courier automatically retries notifications when the downstream provider returns these HTTP error codes:

  • 408 Request Timeout - The provider took too long to respond
  • 429 Too Many Requests - Rate limiting or throttling
  • >=500 Server Errors - Internal server errors, service unavailable, etc.

Provider Failover

Configure multiple providers in a single channel to ensure delivery when your primary provider has issues.

Provider Failover Example

If you configure SES as a backup for SendGrid, Courier will automatically switch to SES if SendGrid experiences an outage or throttling.

Provider failovers are configured in:

  • A template’s channel settings
  • The message.channels.[channel_name].routing_method property of the Send API.

Channel Failover

Configure multiple channels in your routing to ensure your message reaches the recipient.

Channel Failover Example

If you configure a Best of: Email, Push, SMS sequence, Courier will try email first, then push if email fails, and finally SMS if both previous channels fail.

Channel failovers are configured in:

  • A template’s routing configuration, using “Best Of” channels
  • The message.routing property of the Send API

Message Timeouts

Courier uses tiered timeouts to control failover behavior. By default:

  • Message timeout: 72 hours (259200000ms)
  • Channel timeout: 30 minutes (1800000ms)
  • Provider timeout: 5 minutes (300000ms)

These can be overridden using timeout configurations in your send request. All timeouts are specified in milliseconds.

Timeout Configuration

You can configure timeouts at multiple levels:

  1. Global timeouts via message.timeout:

    • message.timeout.provider - Applies to all providers
    • message.timeout.channel - Applies to all channels
    • message.timeout.message - Overall message timeout
  2. Channel-specific timeouts via message.channels.[channel].timeout

    • Example: message.channels.direct_message.timeout
    • Overrides the global channel timeout (message.timeout.channel)
  3. Provider-specific timeouts via message.providers.[provider].timeout

    • Example: message.providers.slack.timeout
    • Overrides the global provider timeout (message.timeout.provider)

More specific timeouts take precedence over global timeouts. For example, message.channels.direct_message.timeout will override message.timeout.channel for the direct message channel.

Example

{
  "message": {
    "timeout": {
      /** Attempt each provider for 10 seconds before moving on to the next provider */
      "provider": 10000,
      /** Attempt each channel for 1 minute before moving to the next channel */
      "channel": 60000,
      /** Overall message timeout of 2 minutes */
      "message": 120000
    },
    "channels": {
      "direct_message": {
        /** Override timeout for direct message channel to 50 seconds */
        "timeout": 50000
      }
    },
    "providers": {
      "slack": {
        /** Override timeout for Slack provider to 20 seconds */
        "timeout": 20000
      }
    }
  }
}