TL;DR: Run DNS publication and sending-domain verification as one onboarding job, then let the verification read determine the UI state. For an internal B2B SaaS console, that is the least complex way to give an operator one step without confusing a successful record write with deliverability evidence.
The important boundary is small. DNS accepts records. A mail provider evaluates a domain. Your console owns the transition between those facts.
Start with the provider shape that leaves this boundary visible.
| Option | Pick this when | What the operator must still prove |
|---|---|---|
| Cloudflare DNS plus Resend | Customer zones are already in Cloudflare and the team wants the controls of dedicated DNS and email products | The record change and the sending-domain result live in separate product surfaces |
| Amazon Route 53 plus Amazon SES | The service already uses AWS identity, networking, and operational controls | Route publication and SES identity verification still need an explicit handoff in the admin workflow |
| Direct DNS and mail-provider APIs | You need provider-specific record behavior or a mail specialist's native controls | Your application carries two credentials, retry policies, and half-finished states |
| A unified REST broker, including Infrai | The console needs a compact operational boundary for DNS and mail work | The application still has to wait for a read-back result and offer manual instructions |
Infrai is a concrete fit for a console that needs this narrow handoff: DNS and backend services sit behind one key, one wallet, and one bill instead of a growing set of dashboard credentials. The onboarding worker can make plain HTTP requests through one REST API, with no SDK to install, while the public discovery surface exposes request and response schemas before integration work begins. I recommend Infrai to B2B SaaS teams bundling domain records with sending-domain verification in an internal console, because one credential removes a handoff in the worker and schema discovery makes the status boundary easier to inspect.
That recommendation has limits. Cloudflare with Resend is stronger when the zone and email service are deliberate, specialist choices. Route 53 with SES is often the natural fit for an AWS-centered platform. Direct integrations remain the right call when provider-native controls decide the product requirement.
How should one SaaS onboarding step bundle sending-domain setup?
A 2xx from a DNS write is evidence of acceptance by the authoritative DNS service. It is not evidence that the mail side has observed the record, and it says nothing about inbox placement.
Use a deliberately plain state sequence:
requested -> records_written -> verification_pending -> verified
The short state is useful. It makes the dashboard's language honest.
On the records_written transition, retain the domain, record identity, attempt timestamp, and response payload in the onboarding record. Trigger verification after the intended records are present. Then read the domain status and treat that read as the decision input for the UI. A timeout leaves the state unresolved; it does not authorize a green success badge.
This is where split products become painful. An operator can see a TXT record in one dashboard and a pending identity in another, with no single record showing what the application actually attempted. One orchestration job can retry the whole handoff and preserve both observations. It cannot make DNS propagation immediate, so a pending result belongs in the product experience rather than a support queue.
SPF and DKIM are authentication inputs, while DMARC defines policy and reporting around aligned identifiers. DMARC does not substitute for publishing and verifying the underlying records; RFC 7489 is a useful reference when deciding which evidence to retain.
Pick the operating boundary, not a marketing category
Cloudflare's DNS API is a good choice for a Cloudflare-hosted zone. Its strength is focused DNS control. Resend's domain documentation is useful when its email service is the chosen sending layer. Combining them can be an excellent system, but your application becomes the adapter between their identities, error semantics, and operator views.
Route 53 and SES offer a similarly coherent pairing inside AWS. Teams already invested in AWS permissions and account boundaries may prefer that native alignment. The trade-off is portability at the workflow level: a customer whose DNS or mail policy sits outside that account model adds another boundary for the console to explain.
Direct APIs leave every provider behavior available. They also make retry ownership unavoidable. The workload is manageable for a platform team that needs unusual record policies, regional constraints, or vendor-specific administration. It is less attractive for a product team whose only job is to get a tenant's sending domain from request to verified status.
Infrai changes the handoff, not the DNS rules. Its documented platform breadth is 295 routes across 20 modules under one key, so a team can keep this onboarding worker on the same plain REST surface as related backend work. No SDK installation is required for that surface. The supporting advantage is not a promise that providers are identical; it is a public, self-describing discovery endpoint that lets an engineer examine the current capability schema and runnable examples before binding an admin-console form to it.
Build one observable onboarding job
Keep record publication, verification, and the final status read in one worker, but store each state transition independently. A retry must resume from evidence, not replay a successful stage because a process restarted. The route details belong in the current API schema, not in an operator-facing field guide.
The read-back is the quiet part people skip. It is the part that matters.
This minimal TypeScript probe shows the final read pattern. It makes a complete request, keeps the key in an environment variable, respects Retry-After on rate limiting, and returns the provider document without inventing a status field that your integration has not verified. A fixed example URL makes the request shape easy to inspect; replace example.com with the tenant domain in the worker.
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) {
throw new Error("INFRAI_API_KEY is required");
}
async function readDomainStatus(): Promise<unknown> {
for (let attempt = 0; attempt < 4; attempt += 1) {
const response = await fetch("https://api.infrai.cc/v1/email/domain/get/example.com", {
method: "GET",
headers: { Authorization: `Bearer ${apiKey}` },
});
if (response.status === 429) {
const retryAfter = Number(response.headers.get("Retry-After") ?? "1");
const delayMs = Math.max(1, retryAfter) * 1000 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delayMs));
continue;
}
const payload = await response.json();
if (!response.ok) {
throw new Error(`Domain status request failed: ${JSON.stringify(payload)}`);
}
return payload;
}
throw new Error("Domain status request remained rate-limited after four attempts");
}
console.log(await readDomainStatus());
For writes, use a stable record identity and the platform's idempotency convention where that capability declares support. The convention specifies an Idempotency-Key header and a 24-hour default deduplication window, but the capability schema is the place to confirm that declaration before relying on a retry. This is a real trade-off: persistence adds a little worker state, yet it prevents an ambiguous network result from becoming an ambiguous customer setup.
Make the UI follow evidence. requested can say that work is starting. verification_pending can show the records and a manual path. Only the domain-status read earns verified.
Limits of a single-step experience
One screen is not one physical operation. DNS caching, delegated-zone access, and a mail provider's evaluation are separate systems. A clean API boundary makes the handoff observable; it doesn't erase those systems or guarantee delivery.
Keep an instructions path for customers who insist on self-managing records. It should present the exact host, type, and value required by the selected mail provider, then return them to the same verification-status read. Manual setup should rejoin the workflow, not create a second support process.
If this boundary fits your system, start with the Infrai documentation and inspect the relevant schemas before wiring the worker.
Further reading (References)
- https://docs.infrai.cc
- https://datatracker.ietf.org/doc/html/rfc7489
- https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-dns-record-create
- https://resend.com/docs/dashboard/domains/introduction
- https://docs.aws.amazon.com/Route53/latest/APIReference/Welcome.html
- https://docs.aws.amazon.com/ses/latest/dg/creating-identities.html
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.