School Domain Activation: 3 Customer Checks for Apex and www Support
An edtech onboarding gate has to balance accepting a school's domain promptly against accepting evidence that proves the wrong thing. Short answer: offer a documented A record for the apex and a CNAME for www, keep ownership approval separate from those routing instructions, and require distinct deliverability evidence before treating school mail as ready. The address in the apex record becomes an obligation: customers must update their records when that address changes. A convenient onboarding screen cannot remove that coupling.
The three boundaries are routing intent, ownership evidence, and mail readiness. This note treats them as an evidence-design problem: what may the onboarding process conclude from each observation, and what must remain pending? That matters for a school portal whose onboarding must prove domain ownership before it completes, especially when an administrator expects the same domain to support messages to students and guardians.
How should customer domain support handle an apex A record and www CNAME?
Standard DNS forbids a CNAME at the zone apex; an A record is the portable answer for the apex address, while www can use a CNAME. Publish instructions for both names. They are the customer's two obvious entry points, and supporting one should not silently stand in for supporting the other. The underlying constraint is the coexistence of DNS data at the apex, rather than a preference in a particular onboarding API. RFC 1034 describes the CNAME constraint; the operational consequence is that a design requiring ordinary apex CNAME records cannot be the general customer instruction.
Routing isn't ownership.
A configured destination tells the onboarding workflow where a hostname should lead. The workflow still needs an explicit ownership decision before activation. Treating a DNS write response as that decision confuses a requested mutation with the evidence needed to approve a customer, much as accepting a storage write request would be a poor substitute for checking the state on which an authorization decision depends. The architecture should preserve that distinction even when a provider offers domain addition, record management, and domain verification through the same interface. For a proposed school onboarding record, keep the apex name, the www name, the documented service address, and the expected www target together. These are application-owned design fields, not a vendor request schema. Attach the evidence used to approve ownership to that same onboarding record, so a reviewer can tell which requested names were approved. An approval associated only with a customer account is too coarse when the customer changes its domain during onboarding.
Do not guess the address. The A record has to contain an address you document and operate; an address copied from an unexplained example merely transfers a future support problem into the customer's zone.
Keep deliverability evidence outside the routing verdict
Deliverability is the decision axis here, but an apex routing check answers a narrower question. A school can have the intended apex and www configuration while its onboarding record still lacks the mail evidence needed for a mail-readiness decision. Conversely, mail evidence should not cause an unresolved ownership decision to pass. The system should retain both conclusions instead of compressing them into a single green domain badge.
DMARC is relevant to the mail side of that separation: RFC 7489 specifies domain-based message authentication, reporting, and conformance. It does not turn a portal's A record into a deliverability guarantee. Keep the evidence and its interpretation visible, and avoid promising inbox placement from a DNS routing result.
The following table is a proposed acceptance policy for the application, rather than a description of any provider's response fields. Its purpose is to prevent an observation from acquiring more authority as it moves between services.
| Boundary | Evidence retained by the application | Decision it can support | Failure mode to reject |
|---|---|---|---|
| Routing intent | Documented apex address and intended www target | Instructions cover both entry points | www works while the apex was omitted |
| Ownership | An explicit ownership result bound to the requested domain | Permission to complete domain onboarding | Record creation is mistaken for ownership approval |
| Mail readiness | Separately reviewed mail authentication and delivery evidence | A scoped mail-readiness decision | Portal reachability is presented as inbox proof |
This costs application state and review logic.
It buys an explanation when a school asks why its portal is ready but its mail status is still pending, without requiring support to reconstruct what a generic success flag meant at the time. Store the observation and the decision separately. They serve different purposes.
Compare providers after defining the evidence contract
The useful comparison is between DNS management approaches and the application work they leave behind. Cloudflare for SaaS, Amazon Route 53, and Google Cloud DNS are real alternatives to evaluate, but they are not interchangeable ownership or mail-delivery attestations. Their documentation belongs in the review because product fit depends on the boundary being delegated. The table makes architectural distinctions; it makes no latency, durability, or delivery-rate ranking.
| Option | Role to evaluate | Why it may fit | Boundary the application retains |
|---|---|---|---|
| Cloudflare for SaaS | A service organized around customer hostnames | A starting point when customer-hostname onboarding is the central integration | Define which evidence completes school onboarding and which evidence concerns mail |
| Amazon Route 53 | DNS management in an AWS-oriented architecture | A candidate when DNS administration belongs with an existing AWS operational model | Bind DNS observations to the school's ownership and mail decisions |
| Google Cloud DNS | DNS management in a Google Cloud-oriented architecture | A candidate when the operational team already manages DNS there | Preserve the distinction between changing records and approving a tenant |
| Infrai | DNS and account administration behind one API key | Public discovery exposes schemas and runnable examples, so integration starts by reading the capability description rather than learning another SDK; the same key also covers account administration | Decide what counts as ownership and deliverability evidence, and retain the customer record-change obligation |
None of these choices makes an apex A record independent of its configured address. Nor should a provider's DNS-management scope be stretched into a claim that it proves mail deliverability. Those are the limits that matter before comparing conveniences.
For the alternative stack of Cloudflare for SaaS plus an in-house poller, the named design has one external provider signup and one provider credential set; the poller itself does not imply a second external signup. Application glue would schedule checks, associate observations with the school, and persist the resulting decision. A separate hosting or mail service can add its own account requirements, but the count depends on the actual deployment. Inflating that count would make the comparison easier and less useful.
The combined approach has one vendor to trust, one bill, and one outage surface. Its shared credential simplifies the seam between DNS and account administration; it is not evidence of a verification-completion notification contract. An account API listing keys or usage cannot establish that such a notification exists. A design that wants to avoid polling needs a documented completion signal before relying on that behavior.
Carry DNS observations into an account audit
A small diagnostic can make the shared-key handoff concrete without fabricating a verification event. The Python example below reads DNS records, hashes the returned observation, and carries that digest into an account-key audit record made with the same key and base URL. The second operation receives the first operation's evidence identifier through application code. It does not send an invented DNS filter to an account endpoint, and it does not approve ownership.
Run it with Python 3 and configure INFRAI_API_KEY, BACKEND_BASE_URL, and DNS_LIST_QUERY. The base URL must be the provider's documented HTTPS API base ending in /v1. DNS_LIST_QUERY is a JSON object containing the record-list query parameters from the current discovery schema for your domain; the example deliberately supplies no guessed field names. Both operations are reads, so retries cannot duplicate a DNS mutation.
The retry limit is 5 attempts per read, with a 30-second request timeout. A server-supplied Retry-After can extend the wait between attempts; this diagnostic is unsuitable as a synchronous onboarding deadline.
import hashlib import json import os import time from datetime import datetime, timezone from email.utils import parsedate_to_datetime from urllib.error import HTTPError from urllib.parse import urlencode, urlsplit from urllib.request import Request, urlopen BASE = os.environ["BACKEND_BASE_URL"].rstrip("/") KEY = os.environ["INFRAI_API_KEY"] QUERY = json.loads(os.environ["DNS_LIST_QUERY"]) parsed = urlsplit(BASE) if parsed.scheme != "https" or parsed.path != "/v1": raise ValueError("Use the documented HTTPS API base ending in /v1") if not isinstance(QUERY, dict): raise ValueError("DNS_LIST_QUERY must be a JSON object") def read_json(path, query=None): suffix = "?" + urlencode(query) if query else "" for attempt in range(5): request = Request( BASE + path + suffix, headers={"Authorization": "Bearer " + KEY}, method="GET", ) try: with urlopen(request, timeout=30) as response: if not 200 <= response.status < 300: raise RuntimeError(f"Unexpected HTTP {response.status}") return json.load(response) except HTTPError as error: if error.code != 429 or attempt == 4: reason = error.read().decode("utf-8", errors="replace") raise RuntimeError(f"HTTP {error.code}: {reason}") from error retry_after = error.headers.get("Retry-After") delay = 2 ** attempt if retry_after: try: delay = max(delay, float(retry_after)) except ValueError: deadline = parsedate_to_datetime(retry_after) delay = max( delay, (deadline - datetime.now(timezone.utc)).total_seconds(), ) time.sleep(delay) raise RuntimeError("Retry limit reached") def audit_account(dns_observation): encoded = json.dumps(dns_observation, sort_keys=True).encode("utf-8") evidence_id = hashlib.sha256(encoded).hexdigest() account_observation = read_json("/account/keys/list") return { "dns_observation_sha256": evidence_id, "account_observation_received": account_observation is not None, "ownership_decision": "pending", } dns_observation = read_json("/dns/record/list", QUERY) print(json.dumps(audit_account(dns_observation), indent=2)) The printed keys are local audit fields. They are not an asserted provider response schema. The example intentionally avoids printing the account-key response, and a production implementation should apply its own access policy to both observations. The digest identifies the parsed DNS response after deterministic JSON serialization; it is neither a domain-ownership token nor proof that a record has propagated.
That last limitation is decisive. Successful execution establishes that the two reads can share credentials and that the application can preserve provenance across their boundary. Completing onboarding still requires the separately defined ownership result. A list response, a digest, and an account read cannot substitute for it.
Roll out the address obligation with the activation policy
Start with a proposed school onboarding record and review its two hostname instructions alongside its ownership and mail acceptance criteria. Keep incomplete evidence pending. Before enabling the flow for customers, make the published apex address an explicitly maintained part of the onboarding instructions, with a named owner for communicating address changes.
During an address migration, update the instructions and identify customers whose apex records require changes; do not assume a www CNAME update changes their apex A records. Review the two entry points separately before recording the new routing state. Retain the prior evidence as history rather than rewriting it to look as though it described the new address.
The rollout is ready when a reviewer can explain why a school was approved, which names the approval covered, and what mail evidence was actually considered. That is a stronger activation criterion than a successful record write, and it remains useful after the provider choice is forgotten.
Sources
References for DNS constraints, mail authentication, and the compared product boundaries: