A game realm can disappear while its DNS zone still serves launchers, status pages, email policy, and player-created names. That operational constraint changes the answer: remove the records owned by the retiring realm first; remove the zone only after proving that the zone itself has one owner, no surviving dependents, and an approved recovery path. TL;DR: Record deletion is a scoped offboarding operation. Zone deletion is a change to the delegation boundary and should be treated as a separate, higher-risk project. For a shared zone, the default is no zone deletion. The distinction matters most while moving game zones away from a registrar-specific API. A migration script can make both actions look like one delete() call, even though their blast radii are nothing alike. The useful abstraction is ownership, not endpoint shape.
Should DNS offboarding mean deleting records or the whole shared zone?
Consider a hypothetical realm named ember under game.example. The matchmaker may use match.ember.game.example, while the realm also has _dmarc.ember.game.example, a status hostname, and names configured for community servers. Turning off the matchmaker does not establish that every other name is disposable.
DMARC makes this concrete. RFC 7489 defines a DNS-published policy record and describes policy discovery using _dmarc names. Deleting an application record and deleting a containing zone therefore operate on different dependency sets. The former can target one workload. The latter can remove policy and other records that were never part of that workload's shutdown ticket.
This is the first boundary: workload ownership is not zone ownership. A team that owns a realm service may have authority to remove its A, AAAA, CNAME, SRV, or TXT records, but that does not imply authority over the enclosing zone. The exact record types are less important than the ownership map attached to each name.
Short version: names outlive processes.
Three gates before any destructive change
I use three gates because they force a vague cleanup request into decisions that can be reviewed. They are intentionally asymmetric: a failed gate blocks zone removal, but it need not block a narrowly scoped record change.
| Gate | Record-level removal | Zone-level removal |
|---|---|---|
| Ownership | Named workload owner approves the exact record set | Accountable owner approves the whole namespace |
| Dependency inventory | Consumers of each target name are identified | Every surviving record, delegated child, and policy name is accounted for |
| Recovery | Previous record values and TTLs are retained | Zone contents, delegation state, and restoration procedure are retained and tested |
The table is a decision aid, not proof. Inventory data can be stale, and query logs can miss dormant clients. A seasonal game event may be quiet for months and still be a live dependency. That is why absence of recent traffic is supporting evidence rather than deletion authority.
The ownership model also settles the customer-owned versus platform-owned decision. If a studio or community operator owns the parent namespace, the platform should emit a removal plan for its own records and let that owner execute or approve it. If the platform owns a realm-specific child zone, it can automate more of the lifecycle, but the same three gates still apply. Control of credentials is not the same as permission to erase a namespace.
Encode intent, not a generic delete button
A registrar migration is a good time to remove provider-shaped operations from application code. The interface below separates a bounded record plan from a zone-retirement plan. It does not assume a vendor API, and it makes a whole-zone request difficult to create accidentally.
type DnsRecord = {
name: string;
type: "A" | "AAAA" | "CNAME" | "SRV" | "TXT";
values: readonly string[];
ttl: number;
};
type RemoveRecords = {
kind: "remove-records";
zone: string;
records: readonly DnsRecord[];
ownerTicket: string;
};
type RetireZone = {
kind: "retire-zone";
zone: string;
inventoryDigest: string;
delegationReviewed: true;
restoreArtifact: string;
ownerTicket: string;
};
type OffboardingPlan = RemoveRecords | RetireZone;
function requiresIndependentApproval(plan: OffboardingPlan): boolean {
return plan.kind === "retire-zone";
}
The discriminated union is small on purpose. It prevents one ambiguous deleteDns(name) function from accepting both a record name and a zone name. A dry run should render the exact names, types, values, and owning tickets that will change. The executor should reject an empty record list rather than interpreting it as “everything.”
There is a real trade-off here. A strict plan format adds paperwork to a small realm shutdown, yet it also creates a portable contract while the underlying DNS provider changes. For a solo builder, that contract is worth more than a clever adapter: it limits the amount of provider-specific logic that can leak into game lifecycle code.
Keep credentials partitioned as well. The routine path for retiring a realm should be capable of changing approved records without holding permission to remove the containing zone. Reserve zone-level capability for the rarer workflow, with separate approval and audit output.
Offboard in phases
Start by freezing creation of new names for the realm and exporting the current record set. Classify each name by owner and consumer. Unknown ownership is not “unused”; it is unresolved work.
Next, lower TTLs only if the change plan and authoritative service support doing so in advance. A TTL change made at deletion time does not retroactively shorten cached data. Then remove the smallest approved record batch, verify authoritative answers and application behavior, and hold before the next batch. Do not combine the provider migration, record cleanup, and zone retirement into one irreversible step.
The final phase is deliberately boring. Preserve the export, approvals, observed results, and restoration instructions. If every record and child dependency has been retired, the namespace owner may schedule zone removal as its own change. If even one owner or dependency remains unclear, stop at record deletion.
No guesswork.
For customer-owned zones, the platform's completion signal should mean “our records are gone,” not “the customer's zone is gone.” For platform-owned child zones dedicated to one realm, zone retirement may eventually be correct, but only after the parent delegation and recovery plan are included in review. This keeps the API migration from silently expanding into an ownership transfer.
What should you measure before copying this approach?
Measure the evidence that can falsify the plan. Count target records, unresolved owners, delegated children, and surviving names outside the retiring workload. Track authoritative lookup results for the exact names being changed, plus application-level health for login, matchmaking, status, and mail-policy paths that share the namespace.
Also measure rollback readiness before execution: can the exported data be parsed, can a reviewer identify the intended zone, and has restoration been rehearsed in an isolated test namespace? A backup file that nobody has validated is only a hope.
Latency and token cost matter in an AI-assisted operations tool, but they are secondary here. Use a model to summarize ownership evidence or draft a plan if that helps; do not let probabilistic output authorize deletion. The executor should consume reviewed, deterministic data, and every destructive action should produce an audit event.
The decision rule is compact: delete records when the retiring game workload owns those records and their consumers are accounted for. Delete a zone only when one accountable owner controls the entire namespace, every dependency has been resolved, and restoration plus delegation changes have been reviewed. Shared zone means record surgery.
Top comments (0)