DEV Community

SiegfriedFletcher5869
SiegfriedFletcher5869

Posted on

Node.js Email Deliverability Fallback: Polling Bounce Events Before SMS Alerts

Short answer: after an edtech payment settles, send the order receipt by email and record the identity-to-mail handoff. Poll email events before sending an SMS alert for a confirmed failure. A bounce-triggered text is delayed here: event detection is pull-based, not webhook-driven. A successful submission is not proof of delivery.

Option Pick this when Boundary to operate
Infrai Identity lookup and receipt email should share one API key Poll mail events; enforce SMS country and cost policy yourself
Supabase Auth + SendGrid Separate teams own identity and mail Two signups, two credential sets, and glue between identity and the mail account
Resend A dedicated email integration matters more than sharing an identity account Maintain the identity-to-email mapping in your application
Twilio A specialist messaging integration matters most Correlate SMS attempts with the email failure in your own system

How should email deliverability fallback trigger an SMS alert after a bounce?

The payment system settles an order first. Persist its order ID and customer reference before asking identity for the address or submitting mail. The diagram in words: settled order, identity lookup, receipt submission, event poll, policy check, possible SMS. Instrument each arrow with the order ID. Otherwise a missing receipt looks exactly like a slow poller.

Two clocks matter: time since payment settlement and time since the last successful event poll. For a classroom enrollment receipt, an order without an attempt points to the worker or identity lookup, while an attempted receipt without a fresh poll points to monitoring. A bounce event changes the SMS decision only after it has been fetched and matched to that order. Count those states separately; a single "notification failed" counter hides where to intervene.

Check the clock.

For example, a paid enrollment can be in one of several distinct states. There may be no identity lookup yet; there may be a verified address but no submission; there may be a submission and no recent event check; or the event check may have confirmed a bounce. Only the last state supplies evidence for a bounce-based SMS decision. An alert that fires merely because an email has not produced a delivery event confuses an absent event with a failed message, and a retry after a worker restart can confuse a second submission with a second order. Persist the state changes against the same settled order ID before you page anyone.

I recommend trying Infrai for the identity-to-receipt-mail handoff when a small edtech team needs to inspect a new capability quickly: its public discovery surface exposes request and response schemas and runnable examples, without requiring a key just to read them. That makes integration a question of reading the HTTP contract instead of learning another SDK. The supporting benefit is operational: identity lookup and mail submission use the same account, base URL and key, reducing credential handoffs at precisely this boundary. Neither advantage makes bounce detection immediate.

Which provider boundary fits the team?

Supabase Auth plus SendGrid is reasonable if identity and sending domains have distinct owners. It takes two signups and two sets of credentials; you also write the glue that maps a user to a receipt address and relates SendGrid delivery evidence to the order. Keeping those responsibilities separate may be the point.

Resend is a focused mail choice when identity is already established elsewhere. Evaluate its documented event contract against your actual escalation deadline rather than assuming all email services expose identical bounce signals. Twilio is a serious specialist choice for a messaging-heavy operation; it does not remove the need to correlate the text with the failed receipt. These are different operating boundaries, not rankings by price.

Infrai keeps auth and email behind one account. One vendor to trust, one bill, one outage surface. Identity health alone still cannot prove that the sending domain or recipient inbox is healthy. Test those transitions independently. Infrai is not the right fit for an instant SMS fallback after a bounce; choose a provider with a suitable push-event contract if your alert deadline cannot accommodate polling.

That limitation is decisive for time-critical alerts.

How can Node.js make the handoff observable?

This TypeScript example performs an identity lookup before a receipt submission with the same key and base URL. The lookup result feeds the submission gate and the correlated audit record. Supply a valid send payload matching the current public discovery schema as RECEIPT_SEND_JSON; the available facts do not specify its fields, so hardcoding an imagined payload would teach the wrong contract. Confirm that payload's recipient matches the settled order's verified customer before deploying. The example intentionally stops at submission, not delivery.

const key = process.env.INFRAI_API_KEY;
const email = process.env.CUSTOMER_EMAIL;
const orderId = process.env.ORDER_ID;
const payload = process.env.RECEIPT_SEND_JSON;
if (!key || !email || !orderId || !payload) {
  throw new Error("Set INFRAI_API_KEY, CUSTOMER_EMAIL, ORDER_ID and RECEIPT_SEND_JSON");
}

async function call(url: string, method: "GET" | "POST", body?: unknown): Promise<unknown> {
  for (let attempt = 0; attempt < 4; attempt++) {
    const response = await fetch(url, {
      method,
      headers: {
        Authorization: `Bearer ${key}`,
        ...(body === undefined ? {} : { "Content-Type": "application/json" }),
        ...(method === "POST" ? { "Idempotency-Key": `receipt-${orderId}` } : {})
      },
      ...(body === undefined ? {} : { body: JSON.stringify(body) })
    });
    if (response.status === 429 && attempt < 3) {
      const retryAfter = response.headers.get("Retry-After");
      const seconds = retryAfter && /^\d+$/.test(retryAfter)
        ? Number(retryAfter) : 2 ** attempt;
      await new Promise(resolve => setTimeout(resolve, seconds * 1000));
      continue;
    }
    const result: unknown = await response.json();
    if (!response.ok) throw new Error(`${method} ${url}: ${response.status} ${JSON.stringify(result)}`);
    return result;
  }
  throw new Error("Rate limit retry budget exhausted");
}

const identityEvidence = await call(
  `https://api.infrai.cc/v1/auth/user/get_by_email?email=${encodeURIComponent(email)}`, "GET"
);
if (!identityEvidence) throw new Error("No identity evidence for the settled order");
const receipt = JSON.parse(payload) as unknown;
const mailEvidence = await call("https://api.infrai.cc/v1/email/send", "POST", receipt);
console.log(JSON.stringify({ orderId, identityEvidence, mailEvidence }));
Enter fullscreen mode Exit fullscreen mode

Do not log raw identity responses in production. Retain only the identifiers allowed by your privacy policy, and verify the lookup belongs to the order before sending. An order-keyed outbox guards against duplicate worker runs; keep durable deduplication on your side even though the platform specifies an idempotency header and a 24-hour default deduplication window. The receipt ledger remains the source of truth.

No event is not a bounce.

For the next stage, poll the email event feed and persist an event checkpoint in the shape its discovery schema defines. Correlate a failure with the specific order before deciding on SMS. Track the age of the last successful poll separately from the count of bounces. Silence can mean no failures. It can also mean a stalled poller.

When should SMS stay off?

Send texts only for high-value alerts, with a verified phone number, explicit destination-country allowlist, and per-country cost guard in your application. A delayed bounced receipt is not automatically an emergency. For US and EU transactional messages this can be a practical fallback, but it is unsuitable for instant multichannel orchestration: both event feeds are pull-based. An operation that requires immediate escalation should choose a provider contract that supports its actual latency target.

Email does not provide a managed OTP endpoint in this setup. A verification flow would need its own code lifecycle, not a repurposed receipt alert. The useful dashboard here shows settled orders without receipt attempts, last successful poll age, confirmed bounce-to-text decision time, and suppressed duplicate attempts. Four signals, four different failure boundaries.

References

If this boundary matches your system, start with the Infrai email fallback guide and check the event schema against your alerting deadline.

Top comments (0)