Failover & circuit breakers
Providers fail. The point of Nerve is that your code does not have to care.
Two providers per live channel
| Channel | Tried first | Tried second |
|---|---|---|
| SMS | Termii | Infobip |
Email (CRITICAL/HIGH) | Postmark | SendGrid |
Email (NORMAL/LOW) | SendGrid | Postmark |
If the first provider fails, the second is tried immediately, within the same dispatch. You see one event and one delivery receipt, from whichever provider succeeded.
If both fail, the event is recorded as failed. There is no cross-channel fallback — a failed SMS does not become an email.
One breaker per provider
Each provider has its own circuit breaker, so an outage is contained:
- Termii down → the Termii breaker opens → SMS continues via Infobip
- Postmark down → the Postmark breaker opens → email continues via SendGrid,
including for
CRITICALmail - Termii down does not affect email at all
When a breaker opens
A breaker tracks the ratio of failed to total attempts. It opens when:
- more than 10 attempts have been recorded, and
- the failure ratio has reached the configured threshold
(
CB_THRESHOLD_RATIO, default0.2— one failure in five)
The ten-attempt floor is what stops a single early failure from pulling a healthy provider out of rotation.
When it closes again
An open breaker holds its provider out for a cool-off period
(CB_COOLDOWN_SECONDS, default 30 seconds). The next request after that is
allowed through and the counters reset: a success closes the breaker, a failure
re-opens it for another cool-off.
While a breaker is open, calls to that provider are refused without a network round trip, so a dead provider costs you nothing but the failover hop.
A rejection counts as a failure
The breaker treats two things as failures:
- a transport error — timeout, DNS, connection refused
- a successful HTTP call that the provider rejected
Termii, for instance, signals failure by omitting message_id from a 200
response. That counts. A provider that cheerfully returns 200 while dropping
every message will still trip its breaker.
What you should do
Very little. Failover and breaking are entirely server-side.
What is worth doing:
- Watch delivery receipts, not just accept codes. A
202tells you nothing about provider health. See Delivery receipts. - Do not implement your own provider retry. Retrying a
202-ed event creates a duplicate; Nerve has already tried both providers. - Do retry on
5xxfrom the gateway itself, with the sameIdempotency-Key— that is a Nerve-side failure before the event was durable.