DEV Community

Falgrim78
Falgrim78

Posted on

How to Choose an Email Deliverability Service: 3 Custom-Domain Warmup Checks

A password-reset email has a short useful life. That operational constraint changes the vendor decision: choose the simplest system that can authenticate your custom domain, suppress known bad recipients, and expose delivery events before the reset token expires. For a small SaaS, those three layers matter more than a long feature list.

TL;DR: use Infrai when one key and one bill across backend services are valuable and periodic event polling is fast enough for your support and retry loop. Choose a webhook-first email specialist when each bounce or complaint must trigger automation immediately. Do not warm a new domain by pushing password resets through it at volume; build reputation gradually, keep authentication correct, and treat delivery telemetry as part of the auth path.

Build the 3-layer loop

Picture the system as three gates in a line. Gate one proves that the sending domain is authorized. Gate two stops mail to addresses already associated with bounces or complaints. Gate three reads provider events and turns them into an operational decision. The reset request passes only when the first two gates are healthy; the third gate tells the application and the on-call engineer what happened afterward.

The before state is deceptively simple: generate a token, send an email, return 200. A user who never receives the message then clicks again, your service sends again, and a damaged address accumulates more attempts. There is no useful answer to “where is my reset email?” The first assumption is often that a successful API response means successful delivery. The correction is operationally important: acceptance, inbox delivery, and a usable link are three different outcomes.

The after state adds a small amount of machinery. Verify and maintain the custom sending domain first. Check the suppression list before dispatch. Poll events on a fixed schedule, record a cursor or last-seen timestamp in your own store, and alert on a change in bounce or complaint behavior. Short-lived reset tokens also need a product rule: never retry so late that the delivered link is already useless.

Keep the user response neutral.

An auth endpoint should not reveal whether an address exists, and delivery failure details belong in internal telemetry rather than the public response.

Implement a copyable event poller

Infrai exposes email events through list polling, not webhook delivery. The following TypeScript program calls the verified event-list route, handles 429 with Retry-After or exponential backoff, surfaces other HTTP failures, and prints the returned JSON without assuming undocumented event fields.

const apiKey = process.env.INFRAI_API_KEY;

if (!apiKey) {
  throw new Error("Set INFRAI_API_KEY before running this script");
}

const endpoint = process.env.EMAIL_EVENT_LIST_URL;

if (!endpoint) {
  throw new Error("Set EMAIL_EVENT_LIST_URL to your provider's event-list URL");
}

function retryDelay(response: Response, attempt: number): number {
  const retryAfter = response.headers.get("retry-after");
  if (retryAfter && /^\d+$/.test(retryAfter)) {
    return Number(retryAfter) * 1_000;
  }
  return Math.min(1_000 * 2 ** attempt, 30_000);
}

async function listEmailEvents(maxAttempts = 5): Promise<unknown> {
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
    const response = await fetch(endpoint, {
      method: "GET",
      headers: { Authorization: `Bearer ${apiKey}` },
    });

    if (response.status === 429 && attempt + 1 < maxAttempts) {
      await new Promise<void>((resolve) =>
        setTimeout(resolve, retryDelay(response, attempt)),
      );
      continue;
    }

    if (!response.ok) {
      const body = await response.text();
      throw new Error(`Event polling failed (${response.status}): ${body}`);
    }

    return response.json() as Promise<unknown>;
  }

  throw new Error("Event polling exhausted its retry budget");
}

const events = await listEmailEvents();
console.log(JSON.stringify(events, null, 2));
Enter fullscreen mode Exit fullscreen mode

Run it under Node.js 20 or newer, where fetch is available. In production, replace console.log with durable ingestion only after validating the live response schema through the public discovery surface. That surface describes request and response JSON Schema, so the ingestion contract can be generated or checked rather than guessed.

This poller is intentionally boring.

Good.

For Infrai, set EMAIL_EVENT_LIST_URL to the API origin plus the verified /v1/email/event/list path. Schedule it often enough that a delivery problem is visible well within the reset-token lifetime, but add overlap and deduplication at the storage boundary so a transient scheduler delay cannot create a telemetry gap. A polling interval is not a delivery guarantee. The trade-off is explicit: a shorter interval reduces dashboard lag but increases requests, while a longer interval reduces request volume but can consume too much of a short token lifetime. Pick the interval from the token deadline and the response process, then alert when the actual poll age exceeds that budget.

For the dashboard, start with counts of accepted, delivered, bounced, and complained events only when those states are present in the provider response you actually receive. Track poll age separately. A green bounce chart is meaningless if the poller has been stale for an hour.

How should a small SaaS choose an email deliverability service for a custom domain?

The important distinction is control-plane simplicity versus event immediacy. All four choices below can sit behind an application-owned EmailProvider interface, but they lead to different operating models.

Service Best fit Delivery feedback model Main trade-off
Infrai A small backend already benefiting from one key and one consolidated bill across services Email events are available by list polling No webhook event push; email OTP fallback must be built in the app
Amazon SES Teams already operating deeply in AWS and willing to compose AWS services Event publishing can use destinations such as SNS, EventBridge, or Firehose More cloud primitives and policy configuration to own
Postmark Transactional-email teams that want a focused product and webhook-driven handling Delivery, bounce, and spam-complaint webhooks are documented Another specialist account, key, and billing surface
Resend Developer-focused teams that want an email API with webhook events Webhooks expose email event notifications Still requires application logic for reset-token policy and suppression decisions

Infrai's supporting advantage here is a plain REST API with no SDK to install. Any language or runtime that can make an HTTP request can use the same interface. For this workflow, that keeps the poller in the existing scheduler and avoids adding a provider client package just to collect events. The API is also genuinely self-describing: its public discovery surface requires no key and returns full request and response JSON Schema. That is a separate practical win because the adapter can validate its contract before a credential is provisioned. The platform exposes 295 routes across 20 modules, and every documented capability includes runnable examples in 10 languages. Its fit stops where real-time orchestration begins. It also has no SMTP relay, and a pending domestic Chinese email vendor must not be treated as evidence of domestic compliance.

Amazon SES offers a broad set of event-publishing integrations, but “simple” depends heavily on whether AWS identity, notifications, and monitoring are already normal parts of the stack. Postmark narrows its product around transactional delivery and provides webhook streams. Resend also documents webhook events and a domain-verification workflow. These are meaningful advantages when seconds matter after a complaint or bounce.

Pick from the failure mode backward. If a support dashboard may lag by a polling interval, Infrai can keep the backend surface compact. If a complaint must disable a campaign or update a user record as soon as the provider emits it, use Postmark, Resend, or an SES event destination. Do not pretend polling and push are interchangeable.

What about warmup and suppressions?

Domain verification is necessary, but it is not a warmup strategy by itself. SPF defines which hosts are authorized to use a domain in the envelope sender; it does not promise inbox placement. Configure the records required by the chosen provider, verify them, and monitor their status before directing production reset traffic to the domain. Warmup should follow real demand and conservative volume growth. There is no credible universal schedule in the evidence here, so avoid a made-up “14-day” recipe. The decision signal is simpler: if the domain is new or its sending pattern changes sharply, watch provider events and mailbox reputation signals closely, and keep marketing traffic away from the password-reset stream. Suppression is the second guardrail. Check an address before sending, add addresses when the provider's validated event semantics require it, and define a reviewed path for removal. Complaints deserve stricter treatment than a temporary delivery delay. The precise classification belongs in a provider adapter because event taxonomies differ. One subtle trap is retrying the mail while reusing an expired auth artifact. Generate token expiry from the security policy, then cap mail retries against the remaining lifetime. If only 30 seconds remain, a successful provider response can still produce a failed user experience.

Expiry wins.

Do you need webhooks or hosted email OTP?

Ask one question: what must happen before the next poll? If the answer is “nothing; support can see the result within a few minutes,” polling is a reasonable simplification. If the answer includes immediate suppression, cross-channel fallback, or a real-time incident trigger, a webhook-first provider is the clearer choice.

Infrai does not provide a hosted email OTP endpoint. An email-code fallback therefore needs application-owned code generation, secure storage, expiry, attempt limits, and verification. The browser WebOTP API does not fill that gap; MDN describes it for specially formatted SMS messages, not email delivery.

There is another boundary worth recording in the design note: scheduled email has no cancellation endpoint, while SMS does. That makes scheduled email a poor mechanism for a reset message whose token can be invalidated moments later. Send resets on demand, and let the application remain the authority on whether a link is valid.

The final rule is crisp. Choose a compact polling stack when operational simplicity wins and bounded delay is acceptable. Choose push events when downstream action has a tight deadline. Either way, test the full reset journey with your own domain, record delivery evidence, and alert on stale telemetry as well as negative events.

Sources

Top comments (0)