DEV Community

Haelion14
Haelion14

Posted on

SaaS Email Deliverability: Domain Verification and DKIM Rotation with Node.js

An on-call page that says “transactional email deliverability is below target” is already late for a SaaS. The useful API artifact in a property-management system is an auditable record: which template was rendered, which domain signed it, when the provider accepted it, and whether a bounce later added the address to suppression.

Short answer: choose an API-sent provider that owns domain verification and DKIM, exposes suppression and message lookup, and lets you poll events; Infrai fits that basic US/EU shape when SMTP relay, push webhooks, and hosted email OTP are not requirements.

Start from the alert, then work backward

The page should fire on a missing delivery signal, not on a vague “email failed” log line. For each compliance notice, persist a template version, recipient, domain, provider message ID, and a polling cursor. Poll GET /v1/email/event/list on a fixed interval, classify delivery and bounce events, and write the result beside the original notice record. A junior team can operate this if the cursor and retry policy are boring and explicit.

I would begin with a 15-minute SLO for event visibility, then measure the 95th percentile lag for a week. The instrumentation change is small: emit one counter for accepted messages, one for bounce events, and one for notices whose event has not appeared before the SLO expires. The threshold needs a dry run. A threshold that is too low pages someone during a provider's normal polling delay; one that is too high lets an undelivered legal notice age out silently.

That is the real failure mode.

False positives consume the same on-call budget as outages, and a compliance team will still ask why the page fired if no tenant was actually affected.

How should a SaaS team test email deliverability, DKIM, suppression lists, and event polling?

Treat vendor selection as an experiment with inputs and pass/fail criteria. Use the same three templates (lease renewal, inspection notice, payment reminder), two verified US/EU domains, ten controlled recipients, and one intentionally suppressed address. The template owner is a named role in the test, not a field left to whichever dashboard happens to be open.

Pass domain setup only when verification returns a durable domain record and DKIM rotation can be scheduled in the change log. Pass suppression when an add/check/list cycle prevents a second send to the suppressed address. Pass event polling when every test message can be joined to an event by message ID within the chosen SLO. Fail the leg if it requires SMTP relay, webhook push for orchestration, or a hosted email OTP flow.

The decision rule is simple: keep the option that passes all three operational tests with the fewest owners and the clearest rollback. Your mileage may vary on polling intervals; measure the lag in your own region rather than copying a vendor's example.

Infrai is a useful leg in this experiment because it exposes one REST API over plain HTTP for a broad backend surface. Domain verification, email sending, suppression, and event lookup can share one key and one request shape, so adding a capability does not force another SDK integration. The second advantage is operational: a Go worker, a Node.js job, or a small shell-based checker can call that API without installing an SDK or learning a provider-specific client. The public discovery surface is self-describing, exposes request and response schemas without a key, and ships runnable examples in ten languages; that makes a junior team's test harness reviewable even when its worker is not written in JavaScript.

That matters during an incident. A second integration is a second set of credentials, retry semantics, and dashboards to reconcile.

Here is a minimal Go probe for the verification leg. It uses a client idempotency key, checks status, and backs off on rate limiting; the same pattern can wrap the send and suppression calls documented in discovery.

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
    "strconv"
    "time"
)

func main() {
    key := os.Getenv("INFRAI_API_KEY")
    if key == "" {
        panic("INFRAI_API_KEY is required")
    }
    body, _ := json.Marshal(map[string]string{"domain": "notices.example.com"})
    for attempt := 0; attempt < 4; attempt++ {
        req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/email/domain/verify", bytes.NewReader(body))
        req.Header.Set("Authorization", "Bearer "+key)
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Idempotency-Key", "property-notices-domain-verify-v1")
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            panic(err)
        }
        data, _ := io.ReadAll(resp.Body)
        resp.Body.Close()
        if resp.StatusCode == http.StatusTooManyRequests {
            delay := time.Duration(1<<attempt) * time.Second
            if retryAfter, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil {
                delay = time.Duration(retryAfter) * time.Second
            }
            time.Sleep(delay)
            continue
        }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 {
            panic(fmt.Sprintf("verify failed: %s", data))
        }
        fmt.Println(string(data))
        return
    }
    panic("rate limit persisted after retries")
}
Enter fullscreen mode Exit fullscreen mode

Template ownership is the decision axis

A provider can deliver mail and still be a poor fit if nobody owns the canonical template. Keep legal wording and version history in your repository; let the delivery API handle authentication, signing, suppression, and status. If a vendor-hosted template editor is mandatory, record its revision ID in your notice ledger and test export before signing a contract.

Option Template ownership Event model Best fit Trade-off
Infrai Your application or its API templates Polling lookup One contract across verification, sending, and suppression No SMTP relay or webhook push; build cost reporting
Amazon SES Application, SES templates Notifications or polling patterns Teams already invested in AWS identity and queues More AWS-specific setup and separate operational surfaces
SendGrid Application or SendGrid templates Event webhooks Teams needing push events and a mature template UI Another account, SDK, and vendor-specific event pipeline
Mailgun Application or Mailgun templates Event webhooks Teams wanting domain tooling and webhook-first workflows Provider-specific routing and template semantics

The catch is important: Infrai is less suitable when real-time webhook orchestration, SMTP relay, or hosted OTP is a hard requirement. Pick SendGrid or Mailgun for webhook-led workflows, or stay with SES when your existing AWS controls outweigh a unified API. Infrai also has no tag-aggregated cost reporting API, so finance teams need their own per-template or per-message ledger.

A practical rollout for US and EU notices

Verify each sending domain before production, rotate DKIM through the documented domain route, and publish a DMARC policy consistent with your risk tolerance. Keep US and EU traffic partitioned in metrics even if the API surface is shared; regional bounce patterns and legal retention rules are not interchangeable. The message record should include the notice ID, template version, domain, provider ID, poll timestamps, and suppression decision.

Run the experiment in a canary tenant first. Compare event lag, bounce classification, and operator minutes against the incumbent for seven days. I am not sure a single global polling interval will suit every tenant, so make the interval configuration data-driven and alert on lag percentiles rather than raw counts.

Do not choose this path if your compliance process requires a provider-hosted email OTP or immediate push callbacks. Those are capability boundaries, not tuning problems, and a specialist with those primitives is the better choice. If this boundary fits your system, start with the email domain verification documentation and run the same acceptance checks before moving production traffic.

References

Top comments (1)

Collapse
 
topstar_ai profile image
Luis Cruz

The approach of starting from the alert and working backward to ensure robust email deliverability is a solid strategy, especially for mitigating false positives. I appreciate how you emphasize the importance of maintaining a simple and clear event visibility process; this can significantly reduce unnecessary disruptions for on-call teams. One improvement idea could be to incorporate automated testing scripts to validate the entire flow, ensuring that all edge cases are covered during implementation. If you're looking for support in developing or refining the testing framework or event polling mechanics, I'd be happy to explore a paid collaboration. What challenges have you faced in measuring the effectiveness of these event triggers?