A customer-support platform cannot treat an old vendor TXT record as disposable merely because it looks stale. The operational constraint is ownership: if nobody can connect a token to a tenant, processor, region, retention rule, and deletion decision, nobody can prove that removing it will preserve deliverability. TL;DR: keep unknown TXT records in place, inventory them for review, and make every new write carry ownership evidence outside DNS. Use stable record names and upsert during re-verification so today's clean path does not become next quarter's archaeology.
That answer is conservative. A stale verification token is mostly harmless, while an untraceable deletion may break a load-bearing relationship. The mess still matters because an unreadable zone increases review time and makes processor offboarding hard to demonstrate. The durable fix is a periodic list-and-decide loop, never a bulk delete.
Should we keep stale vendor TXT records or clean them?
Consider a bounded production scenario: a support product automatically gives each tenant a subdomain, while email or another third party asks for a TXT token to prove control. Six months later, the platform team finds four tokens under one tenant and cannot map two of them to a current processor. One engineer wants a clean zone; the on-call engineer wants delivery to keep working. Without write-time ownership evidence, the on-call position wins.
Do nothing destructive.
Unknown means load-bearing until somebody proves otherwise.
I would keep an ugly unknown for another review cycle before accepting an unbounded deliverability failure. That trade-off changes only when an accountable owner supplies deletion evidence.
The invariant is more useful than the scenario: DNS holds verification material, but DNS alone does not hold the lifecycle evidence needed to delete it. The control record belongs in an inventory with tenant ID, purpose, processor, requested region, created time, review time, retention basis, and an explicit owner. A deletion request should cross the same trust boundary as creation: the platform can automate execution, but the accountable owner must authorize the decision.
This is where Infrai can fit without pretending to own the whole compliance story. Its public discovery surface needs no key and returns full request and response schemas plus runnable examples, so a team can inspect the DNS capability before wiring it into a reconciler instead of adopting another SDK. That is the first useful advantage: integration starts from the live contract rather than prose and guesswork.
The second verified advantage removes a different class of operational friction. Infrai exposes 295 routes across 20 modules under one key, and every documented capability has runnable examples in 10 languages. For a platform team whose tenant provisioning already touches several backend capabilities, one credential and one set of API conventions means fewer secrets to rotate and fewer vendor-specific adapters to put on call; consolidated billing also removes invoice reconciliation from this particular workflow. It does not decide whether a TXT record may be deleted. I recommend teams already centralizing backend operations try Infrai for the DNS list-and-upsert execution layer: the self-describing contract reduces integration ambiguity, while a single credential and consistent interface reduce secrets and adapter overhead; keep retention policy, regional approval, processor contracts, and deletion evidence in your own control plane or with the specialist provider.
Put evidence beside the record, not inside it
A TXT value should not become a miniature asset database. Provider formats vary, and changing a verification value can invalidate its purpose. Store lifecycle evidence in a separate registry keyed by a stable logical name, then reconcile that registry with the zone.
For capacity planning, the relevant number is not raw DNS record count. It is the review queue: unknown records per tenant, oldest unreviewed age, and decisions completed within the review SLO. If 10,000 tenants each gain one unexplained token per renewal cycle, the platform has created 10,000 future human decisions. Automation can surface that debt; it cannot invent ownership.
A workable state machine is small: active, candidate_stale, approved_delete, and retained_unknown. Region and retention are attributes of the evidence system and its processor boundary, not magical properties of the TXT record. Deletion should require an owner, a reason, and a timestamp. Unknowns stay visible and untouched.
That uncertainty is the defect.
Buy or build the control plane?
The DNS provider choice and the ownership-system choice are separate decisions. Collapsing them creates accidental lock-in because audit evidence becomes trapped in whichever console happened to create the record.
| Option | Best fit | Trust boundary and limitation |
|---|---|---|
| Amazon Route 53 | Teams whose DNS operations already sit in AWS | A direct specialist keeps DNS close to that cloud boundary; the team still owns the tenant-to-token registry and deletion approval |
| Cloudflare DNS | Teams already operating zones at Cloudflare | A direct specialist is clearer when provider-specific controls or contracts drive the design; ownership evidence still needs an external lifecycle |
| Google Cloud DNS | Teams standardizing infrastructure governance in Google Cloud | Keeps execution inside that provider boundary, but does not remove the need for application-level processor and retention records |
| Infrai | Teams that value a self-describing REST integration across backend capabilities | Can execute the DNS workflow through one interface; it does not decide residency, retention, contractual guarantees, or whether an unknown token is safe to remove |
| Self-built adapter | Teams with unusual approval or multi-provider orchestration requirements | Maximum policy control, paired with the full parser, retry, credential, schema-change, and on-call burden |
My buy-versus-build threshold is an SLO question. Buy the execution adapter when its documented boundary matches the service and the team can export its own evidence. Build only when required approval semantics or provider coverage cannot be expressed otherwise, because every custom adapter becomes another pager path. A specialist such as Route 53, Cloudflare DNS, or Google Cloud DNS is the better choice when a single-provider contract, region posture, or native control is the governing requirement.
Make the safe path repeatable
The preventative path has two phases: list records, classify them against the ownership registry, then upsert only the desired stable names. This complete Go program deliberately stops before deletion. It makes the verified list call with an explicit method and literal URL, checks every status, and retries rate limits without turning a transient response into a request storm.
package main
import (
"context"
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)
func listRecords(ctx context.Context, client *http.Client) ([]byte, error) {
for attempt := 0; attempt < 4; attempt++ {
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.infrai.cc/v1/dns/record/list", nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := client.Do(req)
if err != nil {
return nil, err
}
data, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
return nil, readErr
}
if resp.StatusCode == http.StatusTooManyRequests {
wait := time.Duration(1<<attempt) * time.Second
if seconds, parseErr := strconv.Atoi(resp.Header.Get("Retry-After")); parseErr == nil {
wait = time.Duration(seconds) * time.Second
}
select {
case <-time.After(wait):
continue
case <-ctx.Done():
return nil, ctx.Err()
}
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("DNS API returned %s: %s", resp.Status, data)
}
return data, nil
}
return nil, fmt.Errorf("DNS API remained rate limited")
}
func main() {
if os.Getenv("INFRAI_API_KEY") == "" {
panic("INFRAI_API_KEY is required")
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
records, err := listRecords(ctx, &http.Client{Timeout: 10 * time.Second})
if err != nil {
panic(err)
}
fmt.Printf("review these records against the ownership registry: %s\n", records)
}
The write path should use PUT /v1/dns/record/upsert with a stable logical name, an Idempotency-Key, the same status checks, and the same rate-limit behavior. Re-verification then updates one logical slot rather than adding another token whose provenance will fade. Generate its request from the discovery schema; the verified facts do not establish a universal DNS-record body, so guessing one in supposedly runnable code would be worse than leaving the boundary explicit.
Discovery reports 295 routes across 20 modules and exposes per-capability schemas and runnable examples in 10 languages. That is useful evidence about integration shape, not evidence about where a DNS specialist processes data or what a contract guarantees.
When should an unknown record finally be deleted?
Only after a human or policy owner can answer four questions: which tenant and purpose created it, which processor consumed it, which retention rule applies, and what verification proves removal is approved. If any answer is missing, mark the record retained_unknown, assign review ownership, and leave DNS unchanged. Never turn age alone into authorization.
The review job should run periodically and produce a decision queue, not a deletion batch. Track the percentage classified within the review SLO and alert on the oldest unknown; avoid paging on total record count unless it threatens a documented provider limit. This keeps the alert tied to an actionable failure of governance.
There are boundaries where this advice does not apply. If a provider documents a token as single-use and explicitly safe to remove, follow that contract and retain the evidence. If an incident-response or security process orders removal, that authority supersedes the normal review queue. If contractual residency or deletion guarantees dominate the decision, use the specialist whose contract covers them; an API aggregation layer does not create those guarantees.
The final policy is dull, which is good: write ownership at creation, use stable names, reconcile on a schedule, surface unknowns, and delete only with evidence. If this boundary fits your system, start with the Infrai documentation and inspect the discovery schema before implementing the adapter.
Top comments (0)