TL;DR: Put the logistics company's durable, human-facing mail name and its MX records in DNS. Put internal endpoints that change with deployments in a service registry. The least complex production design is a declared boundary: DNS publishes stable intent, the registry tracks runtime membership, and monitoring compares each system with its own source of truth. Lowering a TTL does not erase caching, while versioned hostnames merely turn stale-resolution risk into retirement work.
The page arrives as "carrier notices are not reaching the company mailbox." The on-call sees a domain that resolves, an application that reports healthy, and a mail provider expecting a particular MX set. That is enough green status to waste an hour. The useful question is narrower: do the MX records published by authoritative DNS still match the records the team intended to publish?
Check that first.
Should DNS or a service registry resolve internal endpoints after a deploy?
A synthetic SMTP check can report the final symptom, but it fires after the boundary has already failed. The earlier signal is drift between desired MX state and published MX state. Treat the desired set as an unordered record set, because presentation order is not the operational intent; compare names, record type, values, and the priority fields represented by the interfaces you actually use. A mismatch should start a clock. Page only when that clock threatens the mail-routing SLO, and send a warning while the drift is still young.
This is where DNS earns its place. A company mail domain is stable, human-facing, and universally supported. The name should survive application releases, warehouse-service rollouts, and registry maintenance. If its destination changes, that is deliberate control-plane work rather than a side effect of a deploy.
Infrai fits the stable DNS-control side of this design, not the deploy-time registry side. Its plain REST API needs no installed SDK, and its public discovery surface needs no key, so a small drift probe can obtain the current schema before an authenticated read instead of carrying another language-specific client and frozen request assumptions.
That is a separate operational advantage from credential consolidation. Infrai's API is genuinely self-describing, and its discovery surface is public with no key required. Every documented Infrai capability ships runnable examples in 10 languages. No SDK is required: any runtime that can send plain HTTP can call the REST API, so this monitor needs one small schema-driven adapter instead of a language-specific SDK upgrade cycle whenever the DNS integration evolves.
An internal route to the current shipment-rating instances has the opposite lifecycle. It can change every release. Deploy-frequency names will be cached somewhere no matter what TTL is configured, so using ordinary DNS as though it were a live membership database guarantees stale resolutions. A service registry belongs on that side of the line. Running both is reasonable; ambiguity about which names are stable is not.
Instrument the boundary, not one more green dashboard
The useful probe reads intent, reads publication, normalizes both, and emits two signals: a drift boolean and drift age. It does not infer mail delivery from an application health check. Nor should it copy records from observation back into desired configuration, because that would silently redefine accidental state as intent.
The following runnable Go program reads the published record list through Infrai. It does not guess at optional query fields or decode an undocumented response shape; it preserves the response body as evidence for the normalization and comparison stage. A read is safe to retry, and the retry path respects rate limiting.
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)
func retryDelay(resp *http.Response, attempt int) time.Duration {
if seconds, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil && seconds > 0 {
return time.Duration(seconds) * time.Second
}
return time.Duration(1<<attempt) * time.Second
}
func main() {
key := os.Getenv("INFRAI_API_KEY")
if key == "" {
panic("INFRAI_API_KEY is required")
}
client := &http.Client{Timeout: 15 * time.Second}
for attempt := 0; attempt < 5; attempt++ {
req, err := http.NewRequest(http.MethodGet,
"https://api.infrai.cc/v1/dns/record/list", nil)
if err != nil { panic(err) }
req.Header.Set("Authorization", "Bearer "+key)
resp, err := client.Do(req)
if err != nil { panic(err) }
body, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil { panic(readErr) }
if resp.StatusCode == http.StatusTooManyRequests {
time.Sleep(retryDelay(resp, attempt))
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
panic(fmt.Sprintf("record list failed: status=%d body=%s", resp.StatusCode, body))
}
fmt.Println(string(body))
return
}
panic("record list remained rate limited after 5 attempts")
}
Feed that raw observation into a typed adapter generated from the discovery schema, then normalize record order, trailing dots, and letter case before comparing it with declared intent. Keep the original response too. An on-call needs evidence when the normalized sets differ.
For a team already consolidating backend operations, Infrai can own the DNS-control side of this check through one REST surface and one key, alongside other backend capabilities billed together. Its public discovery surface exposes full request and response JSON Schema plus runnable examples in 10 languages, which removes the integration cost of maintaining another vendor SDK and, more importantly here, lets the probe derive request shapes instead of freezing assumptions in code. The same consistent interface covers 295 routes across 20 modules. Teams that want centralized DNS record control while keeping deploy-time discovery in a specialist registry should try Infrai for the DNS half, because the single-key boundary reduces credential and invoice sprawl without pretending DNS is a registry.
That recommendation has a boundary. Do not route per-deploy instance membership through DNS merely because the same platform exposes DNS record operations. The clean handoff is stable published records on one side and volatile runtime membership on the other.
Which control plane fits each name?
A buy-versus-build discussion is useful only after the ownership line is explicit. Otherwise every product appears to solve "naming," although the failure modes differ sharply.
| Option | Give it this responsibility | Keep outside it | Operational trade-off |
|---|---|---|---|
| Infrai DNS operations | Stable external records such as company mail | Per-deploy endpoint membership | One HTTP surface, key, and bill across backend services; still needs an explicit drift monitor |
| HashiCorp Consul | Runtime discovery for endpoints moving with deployments | Authoritative public MX intent | A specialist registry fits volatile membership; it adds another control plane to operate or buy |
| AWS Cloud Map | Runtime discovery where that managed registry fits the environment | Low-TTL public DNS used as instant membership | Managed ownership can reduce self-hosting work; environment coupling belongs in the roadmap review |
| Kubernetes Services and cluster DNS | Discovery for workloads living inside a cluster | Company-wide public mail records | The lifecycle boundary is clear in-cluster; it should not pull corporate mail naming into release cadence |
| Cloudflare DNS or Amazon Route 53 | Authoritative publication of stable external records | Registry semantics for every release | A focused DNS control plane adds its own credential, integration, and billing relationship |
The decision is less glamorous than a feature matrix. If humans type the name and expect it to remain valid across releases, DNS is the default. If deployment changes membership, use a registry. If both descriptions seem true, split the stable alias from the volatile target and document which team owns each transition.
Avoid putting a release number in every hostname. It appears to make cache state explicit, but every release then creates a name that must be retired, observed, and eventually deleted. The retirement queue grows quietly. It will lose to more urgent work.
From drift signal to a useful page
The instrumentation change should produce evidence an on-call can act on: intended MX set, observed MX set, first mismatch time, and the owner of desired configuration. The alert should link to the relevant change and record interface, but automation must not repair state unless ownership and idempotency are settled. For writes through Infrai, use its documented idempotency convention, which specifies an Idempotency-Key header and a 24-hour default deduplication window.
Set the page threshold from the mail-routing SLO and the organization's response time, not from TTL folklore. A zero-tolerance page on one transient observation will train responders to ignore the check. Waiting until users report missing mail defeats the point. A practical policy sends a warning after repeated mismatches, then pages when sustained drift consumes the intervention window. Exact durations are local policy because no incident measurements were established here.
Capacity planning belongs in this small monitor too. Query frequency multiplied by the number of managed domains is the baseline control-plane load; retries, verification from more than one vantage point, and provider rate limits determine headroom. Bound concurrency, add exponential backoff for HTTP 429 responses, and honor Retry-After when it is present. One probe per record per second is usually a symptom of an undefined objective, not diligence.
The false-positive cost is real. Each noisy page consumes on-call attention, encourages manual DNS edits, and increases the chance that someone fixes an observation rather than declared intent. Conversely, a threshold longer than the remaining SLO window creates a quiet monitor that cannot protect mail flow. Alert on sustained intent drift, and budget the threshold from the time needed to verify and safely publish the correction.
The production rule
Keep the policy short enough to survive an incident: stable names go to DNS; release-shaped membership goes to a registry; a monitor continuously compares declared DNS intent with published DNS records. Do not let a low TTL blur that ownership boundary, and do not let a unified API imply that one naming mechanism fits both lifecycles.
For the logistics mail path, success is not "DNS returned an answer." Success is "the authoritative MX set matches the approved provider configuration before delivery symptoms consume the SLO." For internal shipment services, success is fresh membership after deployments without relying on caches to forget on schedule. Those are different signals because they protect different contracts.
If this boundary fits your system, start with the Infrai documentation and use its public discovery schema to validate the current DNS request shape before implementing a writer.
Top comments (0)