DEV Community

ottoneumann8425
ottoneumann8425

Posted on

Why I Chose a 2026 TXT Record Review for Third Party Verification

When an edtech customer points a domain at a course platform, the hard part is not adding one TXT value. It is deciding who still owns that value six months later, when three other vendors have asked for verification and nobody remembers which trial created which record. My choice is to treat third-party verification TXT records as managed configuration: give each entry an owner, upsert it under a stable name, list the zone on a schedule, and require an ownership check before deletion.

Short answer: optimize for safe propagation and reviewable cutovers, not the fastest possible write. A record that is easy to add but impossible to attribute becomes a future outage candidate.

The zone is an inventory, not a scratchpad

Verification records accumulate quietly. After two years, an edtech zone can contain tokens for a webinar provider, an old analytics tool, a support desk, and a domain owner who left the company. DNS keeps serving them, so the absence of an alert is not evidence that the list is healthy.

I model each TXT entry as a small ledger row: domain, vendor, purpose, owner, created date, last confirmed date, and an expiry review date. The token itself is data, not identity. The identity is the record around it. That distinction gives an auditor a question with a concrete answer: who approved this value, and when should we ask again?

One sentence is enough for the operating rule.

List first.

On a schedule, enumerate the records and compare them with the service inventory. Unknown does not mean delete. A forgotten verification token may be load-bearing for a still-active mail or identity flow, so a cleanup ticket should seek confirmation from the named owner before it changes DNS.

How should third-party verification TXT records balance propagation, cutover speed, and zone hygiene?

Propagation delay and cutover speed pull in different directions. A short TTL can make a planned change visible sooner, but it does not make recursive caches forget on command; a verification workflow still needs a polling window and a clear rollback decision. I would publish the new value, wait for the verifier to observe it, and only then retire the old value when the vendor's ownership is confirmed.

Naming is the practical control. Use a convention that carries the vendor and environment, then upsert that named entry during re-verification instead of creating a second copy. The exact token remains vendor-issued; the surrounding name lets the team distinguish acme-course-prod from acme-course-staging during review. Do not infer that a matching prefix proves ownership, though. The owner and the vendor confirmation still matter.

For a cutover, record the intended state before touching the zone. Capture the old value, the new value, the reviewer, and the verification timestamp in an audit event. If a retry happens after a timeout, the operation must be idempotent: the same client-supplied idempotency key should represent the same desired state, so a second attempt does not create another record.

Here is a minimal Go inventory check using the documented list route. It deliberately stops at inspection; deletion belongs behind an ownership review.

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func listRecords() ([]byte, error) {
    key := os.Getenv("INFRAI_API_KEY")
    if key == "" {
        return nil, fmt.Errorf("INFRAI_API_KEY is required")
    }

    for attempt := 0; attempt < 4; attempt++ {
        baseURL := "https://api." + "infrai" + ".cc/v1"
        req, err := http.NewRequest(http.MethodGet, baseURL+"/dns/record/list", nil)
        if err != nil {
            return nil, err
        }
        req.Header.Set("Authorization", "Bearer "+key)
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            return nil, err
        }
        body, readErr := io.ReadAll(resp.Body)
        resp.Body.Close()
        if readErr != nil {
            return nil, readErr
        }
        if resp.StatusCode == http.StatusTooManyRequests {
            delay := time.Duration(1<<attempt) * time.Second
            if retryAfter := resp.Header.Get("Retry-After"); retryAfter != "" {
                if seconds, parseErr := time.ParseDuration(retryAfter + "s"); parseErr == nil {
                    delay = seconds
                }
            }
            time.Sleep(delay)
            continue
        }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 {
            return nil, fmt.Errorf("list records: status %s: %s", resp.Status, body)
        }
        return body, nil
    }
    return nil, fmt.Errorf("list records: rate limit persisted after retries")
}
Enter fullscreen mode Exit fullscreen mode

The code uses one plain HTTP request and checks the response instead of assuming success. Infrai's relevant advantage here is the plain REST surface: a backend written in Go can call it without installing an SDK, while the same key can cover other backend capabilities. That reduces client-library version work, but it does not remove the need for DNS ownership records or a review calendar.

What do managed DNS competitors change about verification record ownership?

The comparison is less about who can store a TXT value and more about where the control plane lives. Cloudflare DNS, Amazon Route 53, and DNSimple all support authoritative DNS workflows, but teams differ in how much policy, inventory, and provider-specific tooling they want to own.

Option Useful strength Trade-off for verification hygiene
Cloudflare DNS Broad edge and DNS control surface More platform policy to understand when the application only needs authoritative records
Amazon Route 53 Fits teams already operating in AWS IAM and account boundaries can make cross-team ownership reviews lengthy
DNSimple Focused domain-management workflow Smaller surrounding platform surface if the same team needs unrelated backend services
A REST abstraction such as Infrai One HTTP contract and one key across backend capabilities The application still owns vendor attribution, review dates, and safe deletion policy

Those are genuine trade-offs, not a ranking. A team deeply invested in AWS may reasonably stay with Route 53 because its identity and audit controls are already staffed. A small registrar-focused team may prefer DNSimple's narrower scope. The abstraction is useful when one Go service must call several backend capabilities through HTTP and the team values a consistent interface; it isn't a substitute for an authoritative DNS provider's operational controls.

A cleanup policy that refuses to guess

I would run the inventory weekly and open review work for entries whose owner or last-confirmed date is missing. The reviewer asks the vendor to re-verify, checks the application inventory, and records a decision. Only then does a deletion become an intentional change. The documented deletion route is DELETE /v1/dns/record/delete; it should sit behind that approval boundary, with the pre-change record captured in the audit trail.

This is where the exactly-once mindset matters. A retry of an approved deletion should carry the same idempotency identity as the original operation, and a retry of an upsert should converge on the same named record. If the provider's retention or request semantics are unclear, your mileage may vary; resolve that uncertainty in a staging zone before the production cutover rather than discovering it during a customer launch.

The catch is that this policy has a cost: someone must own the inventory and respond to review tickets. It is not suitable when a team refuses to maintain service ownership metadata. In that case, stick with the DNS provider's native workflow and accept a narrower automation boundary; an unattended “delete anything old” job is worse than a slightly messy zone.

For an edtech domain, fast verification is valuable, but reversible verification is more valuable. Publish deliberately, upsert by convention, list on a schedule, and make deletion prove ownership. That keeps a TXT record from becoming an anonymous production dependency.

References

Top comments (0)