A hostname cutover for an edtech tenant is a DNS ownership decision before it is a deployment task. Short answer: support an apex A/AAAA path when customers need their bare domain, but keep a www-only path as the lower-coupling default when you cannot control the customer zone; document the boundary and rehearse rollback before changing traffic.
| Choice | Works for | Coupling you accept | Rollback shape |
|---|---|---|---|
| Customer apex A/AAAA | A school wants example.edu in the browser |
The customer must publish address records and keep them aligned with your ingress | Restore the previous A/AAAA values, then wait for cached TTLs |
Customer www CNAME |
You want a simple delegated hostname such as www.example.edu
|
The apex redirect and mail policy remain the customer's job | Move the CNAME target back while the old target is still serving |
| Platform-owned subdomain | You need automatic onboarding, such as school-42.yourapp.test
|
The platform owns the zone and the tenant gets less DNS control | Flip one platform record, with no customer ticket |
My rule for a one-person product is blunt: choose the row that leaves the fewest human actions during an incident, not the row with the prettiest URL. Revenue per hour matters. DNS support that creates a support thread for every renewal is a tax on shipping.
What does apex A records versus www-only support change for customer domains?
The apex (also called the zone apex or bare domain) is example.edu, while www.example.edu is a name below that apex. A CNAME maps a name to another name, but a zone apex also has to carry the zone's SOA and NS records. That is why an apex CNAME is not a portable assumption: traditional DNS rules do not let the apex replace those required records. An A record maps a name directly to an IPv4 address; an AAAA record does the same for IPv6.
For www, the customer can usually publish a CNAME to your hostname. Your service can then change the CNAME target behind that stable customer record. For an apex, the customer generally publishes your current A/AAAA addresses, or uses a DNS provider feature that synthesizes apex behavior. That feature is provider-specific, so it belongs in the support matrix rather than in a universal integration contract.
This distinction creates coupling in two directions. With customer-owned zones, the tenant controls DNS, but your cutover depends on their change window, TTL choices, DNSSEC policy, and registrar workflow. With a platform-owned zone, you can automate the record and rollback, but the tenant accepts a platform-controlled namespace and may need a redirect from its corporate apex.
The browser does not care which ownership model you picked. Operations does.
A practical documentation page should state the exact supported names, record types, and proof required before activation. It should say whether www is canonical, whether the bare domain redirects, which address families are published, and who changes records during a rollback. Avoid promising “apex support” without naming the mechanism: “publish these A and AAAA values” is testable; “add our CNAME at the root” is often not.
How should an edtech team document a customer-domain cutover and rollback?
Treat a domain as a small state machine. requested means the tenant has entered a hostname. proving means the ownership challenge is present. ready means authoritative DNS answers match the expected record set and TLS is available. active means application traffic and redirects have passed checks. rollback-ready means the previous target is still serving and its record values are stored.
Store intent separately from observation. Intent might say www.example.edu should point at tenant-42.edge.example.net. Observation is what authoritative name servers actually return at check time. The difference catches drift: a customer can edit a record after onboarding, or a registrar can import an old zone file.
Here is a provider-neutral TypeScript shape for the control plane. It does not assume a vendor API; the adapter can call an internal console, a registrar integration, or a standard DNS service.
type DomainState =
| "requested"
| "proving"
| "ready"
| "active"
| "rollback-ready";
type RecordIntent = {
fqdn: string;
type: "A" | "AAAA" | "CNAME" | "TXT";
values: string[];
ttlSeconds: number;
};
type DomainSnapshot = {
state: DomainState;
intent: RecordIntent[];
observed: RecordIntent[];
previous: RecordIntent[];
};
function canActivate(snapshot: DomainSnapshot): boolean {
const same = (a: RecordIntent, b: RecordIntent) =>
a.fqdn === b.fqdn && a.type === b.type &&
a.values.slice().sort().join("|") === b.values.slice().sort().join("|");
return snapshot.state === "ready" &&
snapshot.intent.every((wanted) =>
snapshot.observed.some((actual) => same(wanted, actual)));
}
function rollbackPlan(snapshot: DomainSnapshot): RecordIntent[] {
if (snapshot.previous.length === 0) {
throw new Error("rollback target is not recorded");
}
return snapshot.previous;
}
The important part is the recorded previous set, not the function names. Before activation, keep the old address or CNAME target live long enough to receive a rollback. A rollback is a DNS write plus a cache wait; it is not an instant switch button.
Use two independent checks. First, query the authoritative servers for the customer zone to verify publication. Second, resolve from a few recursive resolvers and make an HTTPS request with the expected Host header. The first check tells you what the zone owner published. The second tells you what a real learner, teacher, or administrator may still see from cache.
For email, do not treat a successful web request as proof that the domain is ready. SPF, DKIM, and DMARC are separate records and separate operational promises. DMARC's policy and reporting model is specified in RFC 7489, and a web cutover should not silently rewrite those records. Keep mail records in the customer-owned inventory even when the application hostname is platform-owned.
Which failure modes make the ownership choice expensive?
The first failure is an apex assumption. A setup guide tells a school to add a CNAME at example.edu; its DNS host rejects the record or silently offers a proprietary alias. The tenant cannot complete onboarding, and your support queue inherits a protocol mismatch.
The second is split authority. A registrar delegates example.edu to one set of name servers, while an old DNS dashboard still shows the records your team edits. The dashboard looks correct. The public answer is not.
The third is a rollback with no runway. Someone lowers the TTL five minutes before cutover, changes the address, sees one successful test, and deletes the old endpoint. Recursive caches do not all expire on the same clock, and a client can continue using the old value. Keep the old endpoint healthy for at least the documented cache window and define the stop condition before the change.
The fourth is certificate timing. DNS publication and certificate issuance are coupled in the user experience but not in the same control loop. Mark a domain ready only after the certificate is usable for the exact hostname, including the apex and www variants you promise.
The fifth is invisible drift. A tenant edits an A record to point at a parking page months later. Your database still says active. Periodic authoritative observations, an audit log, and an alert on unexpected values cost less than rediscovering the issue during a class registration deadline.
For a real cutover, write the runbook as if the person on call has never seen the zone. Start with the customer and tenant identifiers, then capture the current authoritative name servers, the current A, AAAA, CNAME, TXT, and MX answers, and the exact TTL values returned by those servers. Record the old application target and keep its health check green. Publish the ownership challenge, wait for an authoritative match, and only then stage the new target. During the change window, check the apex and www separately because a redirect can hide a stale answer on one name. Check from at least one recursive resolver outside your office network, and keep the timestamp and resolver address beside each result. If the HTTPS check fails, stop before changing mail records. If the new service answers but the certificate does not cover the requested hostname, stop as well. A rollback ticket should name the previous record set, the operator allowed to restore it, and the time at which the old target may finally be retired. Those details feel fussy until a school is between classes and nobody knows whether the failure is DNS, TLS, or an application route. Then the notes become the incident boundary, and the one-person team can spend its next hour shipping a fix instead of reconstructing yesterday's state.
Keep it boring.
I once assumed a short TTL would make a cutover reversible. It did not; the old target had already been removed, so the DNS change had nowhere safe to return. The correction was procedural: retain the previous target, test it continuously, and make rollback a first-class state. That is a small operational habit with a large revenue-per-hour payoff.
When is the runner-up a better fit?
A platform-owned subdomain is the better fit when a tenant needs a working URL in minutes, cannot edit DNS, or wants the product team to own every record. It is also useful as a staging hostname while a customer proves its apex. The trade-off is branding and control: some schools require their corporate domain, and a platform namespace may not satisfy procurement or accessibility documentation.
The www-only path is the better fit when customers have heterogeneous DNS providers, you need CNAME-based indirection, and a bare-domain redirect is acceptable. It is not suitable when the organization requires the apex itself in bookmarks, certificate names, or policy documents and will not operate a redirect.
A customer-owned apex is the better fit when the tenant needs full DNS control, already operates a managed zone, and can accept a documented A/AAAA update during cutover. It is not suitable when your service changes ingress addresses frequently or when support cannot verify authoritative records. In those cases, a stable delegated name reduces coupling.
Your documentation should make this choice visible before onboarding: show the three paths, name the owner of each record, list the verification evidence, and state the rollback deadline. Do not hide the constraint in a troubleshooting page.
Ship weekly. Outsource the undifferentiated DNS ceremony where the boundary is clear, but keep the state, evidence, and rollback decision in your application.
Top comments (0)