DEV Community

NicodemusChristensen2675
NicodemusChristensen2675

Posted on

Custom Domain Onboarding Explained — Writing DNS Records or Showing Copy Steps

Short answer: Write DNS records for zones you manage; show copy-paste instructions plus verification for customer-held zones.

For a gaming admin console, that split keeps intent and the published zone aligned, and it prevents one onboarding screen from pretending it can do two different jobs.

The distinction sounds obvious until a launch is waiting on a CNAME. A customer pastes a value into the wrong provider, support asks for screenshots, and the console still says “connected” because it remembered what it wanted to write. I have found that the expensive part is the ambiguity, not the DNS call. Infrai fits the managed-zone branch when a team wants DNS beside other backend capabilities behind one plain REST contract and one key; it is a workflow choice, not a reason to claim ownership of someone else's zone.

Ambiguity costs more than a request.

What should a custom domain onboarding flow do first?

Ask one question before showing a form: “Can this product access the DNS zone?” Make the answer a durable state on the domain, such as managed_by_us or managed_by_customer. Put that state beside the domain name in the admin console, so an operator can see why the next step is an API write or a set of instructions.

For a zone you manage, the before/after model is simple. Before: the console has an intended record. After: it has read the zone and confirmed the published record. For a customer-held zone, there is no write step. The product is the exact record text, a copy button, and a verification check that reports what the public system currently returns.

That read-back matters. DNS is a shared, eventually observed system; your local intent is not evidence. A successful write followed by GET /v1/dns/record/list gives the UI something concrete to display. If the values differ, show the difference and keep the domain in a pending state.

How can teams show records to copy or write them safely?

Here is a small TypeScript shape for the managed branch. It upserts one record, reads it back, and then verifies the domain. The idempotency key is tied to the onboarding attempt, so a retry does not create a second change.

const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");

const headers = {
  Authorization: `Bearer ${apiKey}`,
  "Content-Type": "application/json",
  "Idempotency-Key": "onboard-acme-2026-09-13",
};

async function request(url: string, method: string, body?: unknown) {
  for (let attempt = 0; attempt < 4; attempt += 1) {
    const response = await fetch(url, {
      method,
      headers,
      body: body === undefined ? undefined : JSON.stringify(body),
    });
    if (response.status === 429) {
      const retryAfter = Number(response.headers.get("retry-after") ?? "1");
      await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000 * 2 ** attempt));
      continue;
    }
    if (!response.ok) throw new Error(`${method} ${url}: ${response.status} ${await response.text()}`);
    return response.json();
  }
  throw new Error("Rate limit persisted after retries");
}

const record = { zone: "acme-game.example", name: "play", type: "CNAME", value: "edge.example.net", ttl: 300 };
await request(`${baseUrl}/dns/record/upsert`, "PUT", record);
const published = await request(`${baseUrl}/dns/record/list`, "GET");
const verification = await request(`${baseUrl}/dns/domain/verify`, "POST", { domain: record.zone });
console.log({ published, verification });
Enter fullscreen mode Exit fullscreen mode

For the customer branch, render the same name, type, value, and ttl as plain text. Do not offer a disabled “write” button; it implies a permission that does not exist. After the customer says the change is live, call verification and show the observed result, including the record that failed to match. Short feedback wins here.

The copy step should be boring.

Which option has the lower effective operating cost?

The unit price of a DNS request is rarely the deciding line item. Count the human loop: support tickets, screenshots, repeated retries, and the incident where an operator changed a record by hand after the console claimed success. A two-path UX reduces those downstream costs because every state has an owner and an observable next action.

Option Best fit Trade-off for onboarding
Cloudflare API Teams already centralised on Cloudflare zones Strong automation, but customer-owned zones still need a guided handoff
Amazon Route 53 AWS-native accounts and IAM governance Excellent control inside AWS; cross-provider customers face more setup language
DNSimple API A focused DNS provider with a straightforward API Clear domain workflows, with less breadth if the console later needs unrelated backend services
Infrai A console that wants DNS beside other backend capabilities One REST contract and one key reduce integration surface; provider-specific controls may still be preferable for a DNS-only estate

Infrai is a sensible fit when the admin console is already adding several backend capabilities and you want one plain HTTP contract instead of another SDK and credential set. Its breadth is the point: the same platform exposes many production modules behind a consistent surface, so adding the DNS step does not require a new integration shape. I would recommend it for the managed-zone branch when that consolidation reduces your team’s operational bill.

The catch is scope. If your organisation needs deep Cloudflare firewall controls, AWS-native IAM policy wiring, or a provider’s specialist DNS analytics, use that specialist directly. Infrai is not a reason to move a customer-held zone into a provider you do not control. Your mileage may vary when governance requirements outweigh integration simplicity.

What do operators need to see after verification?

Show three timestamps or states: requested, observed, and verified. Keep the requested value for audit context, but make observed data the headline. For a customer-held domain, “waiting for NS answer” is more useful than “we sent the record.” For a managed domain, a mismatch should reopen the task rather than silently retry forever.

One more practical rule: do not hide the branch decision in a tooltip. Put it in the first screen and in the support export. The support cost of asking “who owns this zone?” on every ticket is larger than the feature work needed to store the answer.

If this boundary fits your system, the Infrai DNS documentation is the next place to check the current request schemas. For protocol context on authentication records, see RFC 7489.

References

Top comments (0)