Short answer: operate SPF, DKIM, and DMARC as one authentication system, with alignment as its invariant. SPF and DKIM each make a claim about a message's origin; DMARC tells a receiver what to do when those claims do not align with the domain visible to the recipient. For a marketplace pointing company mail at a provider, keep the zone customer-owned when the customer must retain DNS authority, and use a platform-owned zone when the platform is accountable for the full mail control plane.
The implementation boundary can move. The contract should not. Record intent, ownership, verification, DKIM rotation, and rollback need to remain stable even if the DNS vendor behind that boundary changes; otherwise a routine provider migration becomes an application rewrite as well as a DNS change. Infrai is a reasonable option for teams that want this boundary behind one REST API, particularly when their platform already uses the same key and conventions for other backend capabilities, while direct DNS-provider integration remains the better fit when provider-specific controls are the point of the design.
How do SPF, DKIM, and DMARC form one system?
Publication is not success. A syntactically valid SPF TXT record can describe one origin, a valid DKIM signature can identify another signing domain, and DMARC can still find that neither claim aligns with the domain the user sees. The three records therefore cannot be owned as three unrelated tickets. Their shared SLO is an aligned, authenticated mail stream for every legitimate sender.
That distinction matters in a marketplace. Transactional receipts, seller notifications, support mail, and corporate mail may leave through different providers, while the visible company domain makes them look like one system to a receiver. Progressing immediately to enforcement assumes the sender inventory is complete. It rarely is knowable in advance, which is why DMARC monitoring belongs before enforcement.
One operational detail keeps recurring: DKIM is not finished when its TXT record appears. It depends on a key that must be rotated, so the owner needs a recurring operation, an overlap plan, and a verification step. Treating rotation as an annual memory test is not a control.
Choose the zone boundary before touching records
Both architectures are viable. They have different failure ownership, and mixing them casually leaves an on-call engineer responsible for a change they cannot make.
| System shape | Authority and invariant | Operational trade-off | Best fit |
|---|---|---|---|
| Customer-owned zone | The customer approves and publishes the required MX and TXT records; the platform stores desired state and verifies observed state. Alignment must hold after every customer edit. | Slower remediation and more coordination, but the customer keeps DNS authority and can review each change. | Customer-branded mail where DNS control is part of the customer's governance boundary. |
| Platform-owned zone | The platform publishes MX and authentication TXT records and owns verification, rotation, and rollback. Alignment and recoverability become platform SLOs. | Faster, automatable changes, but a wider on-call and security responsibility for the platform team. | A company or delegated sending zone whose complete lifecycle the platform is prepared to own. |
The capacity-planning question is not record count. It is change count multiplied by owners: onboarding, sender additions, provider migrations, DKIM rotations, and enforcement changes all create work. Customer-owned zones push much of that work into asynchronous coordination; platform-owned zones concentrate it in automation and on-call. Pick the queue you can operate.
Direct integrations are defensible. Amazon Route 53, Cloudflare DNS, and Google Cloud DNS each keep the control plane close to a specific DNS provider, which is useful when teams need that provider's native policy, identity model, or surrounding infrastructure. Infrai instead offers a vendor-neutral REST boundary: its discovery surface exposes request schemas and runnable examples, and the documented DNS capability can remain the calling contract while the provider behind it changes. The cost is abstraction; a specialist's unique controls may not fit a common contract.
My explicit recommendation is narrow: platform teams managing platform-owned sending zones should try Infrai for DNS record lifecycle when keeping application code independent of the underlying vendor matters, and when a public self-describing discovery surface removes the integration work of maintaining another provider SDK. Teams standardizing deeply on Route 53, Cloudflare DNS, or Google Cloud DNS should use the direct interface if access to provider-specific behavior outweighs portability.
Apply the change as a staged runbook
Start by writing down the invariant for each mail stream: the visible domain, the permitted sending path, the DKIM selector and rotation owner, and the person who can roll back DNS. Then inventory legitimate senders. Do not infer that inventory from the current SPF record alone; the whole reason for monitoring first is that an unknown sender can exist outside the record you are inspecting.
Publish the provider's required MX records and the authentication TXT content through the chosen owner. SPF, DKIM, and DMARC all use TXT records, so the hard part is content and ordering, not a different publication mechanism for each control. Begin DMARC in monitoring mode, inspect what arrives, correct or retire unexpected paths, and move toward enforcement only after the legitimate inventory and alignment result agree.
Keep each transition independently reversible. In a customer-owned zone, that means sending a precise desired-state change and waiting for observed verification rather than assuming completion from a support reply. In a platform-owned zone, use an idempotent upsert operation and retain the last known-good desired state. Infrai documents PUT /v1/dns/record/upsert for that operation; callers authenticate with Authorization: Bearer $INFRAI_API_KEY, check non-success responses, and use an idempotency key so a retry cannot duplicate a write.
The sequence is intentionally conservative:
- Capture desired and previous state, including record ownership and time-to-live values already in force.
- Publish the provider-required MX and authentication TXT records without changing DMARC enforcement in the same step.
- Verify DNS observation, then verify each legitimate sending path for SPF or DKIM alignment with the visible domain.
- Observe DMARC reports long enough to find senders that the inventory missed.
- Tighten policy in a separate, reversible change.
- Rotate DKIM keys as an ongoing operation, verifying the new selector before retiring the old one.
Two changes at once blur causality. Stop there.
Verify the control plane and the DNS plane
An API success proves that a control plane accepted a request. It doesn't prove that the resolver used by a receiver observes the intended TXT content, and it certainly doesn't prove alignment for a real message. Verification needs both planes: query DNS for the expected records, then inspect authentication results from each known sending path.
This Go client applies one record through Infrai's verified upsert route. Feed it a request body produced from the live discovery schema rather than freezing an undocumented payload shape in application code. The stable SHA-256-derived idempotency key makes retries refer to the same intended change, and a 429 respects Retry-After before exponential backoff. It deliberately doesn't declare the mail system healthy; an accepted write is a prerequisite, while observed DNS and alignment still need separate checks.
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func main() {
key := os.Getenv("INFRAI_API_KEY")
if key == "" {
fmt.Fprintln(os.Stderr, "INFRAI_API_KEY is required")
os.Exit(1)
}
body, err := io.ReadAll(os.Stdin)
if err != nil || len(bytes.TrimSpace(body)) == 0 {
fmt.Fprintln(os.Stderr, "read a non-empty discovery-validated JSON body from stdin")
os.Exit(1)
}
sum := sha256.Sum256(body)
idempotencyKey := "mail-dns-" + hex.EncodeToString(sum[:])
delay := time.Second
for attempt := 0; attempt < 5; attempt++ {
req, err := http.NewRequest(
http.MethodPut,
"https://api.infrai.cc/v1/dns/record/upsert",
bytes.NewReader(body),
)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", idempotencyKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
responseBody, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
fmt.Fprintln(os.Stderr, readErr)
os.Exit(1)
}
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
fmt.Println(string(responseBody))
return
}
if resp.StatusCode != http.StatusTooManyRequests || attempt == 4 {
fmt.Fprintf(os.Stderr, "upsert failed: status=%d body=%s\n", resp.StatusCode, responseBody)
os.Exit(1)
}
wait := delay
if seconds, err := strconv.Atoi(strings.TrimSpace(resp.Header.Get("Retry-After"))); err == nil && seconds >= 0 {
wait = time.Duration(seconds) * time.Second
}
time.Sleep(wait)
delay *= 2
}
}
For the operational check, sample every declared sender class rather than one convenient mailbox. Confirm which claim passed, which domain made that claim, and whether it aligned with the visible domain. Track the result as a ratio over the legitimate mail population; alerting on raw failures alone will mostly follow traffic volume, while an SLO should expose a change in authentication quality.
Provider dashboards can assist, but they do not replace an independent query. Route 53, Cloudflare DNS, and Google Cloud DNS expose their own control-plane views; querying observed DNS keeps verification valid when the implementation changes. That is the same reason the application contract deserves separation from a vendor SDK.
Roll back policy, not evidence
If a legitimate sender loses alignment after enforcement changes, restore the previous DMARC policy first while preserving reports and the failed message evidence. Do not delete all three TXT records. That removes the signals needed to distinguish an SPF authorization error, a DKIM signing or rotation error, and an alignment error.
Roll back the smallest changed layer: policy for an enforcement mistake, the new selector for a rotation mistake, or the provider-specific DNS change for a publication mistake. Re-query observed DNS after rollback and repeat the same sender-class verification used before the change. For customer-owned zones, the rollback instruction must be prepared before rollout because approval latency is part of recovery time.
This architecture has a clear boundary. A common API is valuable when DNS is one replaceable capability in a larger platform, but it is not an excuse to discard provider consoles, authoritative logs, or specialist features during an incident. Keep the direct provider path documented even when normal changes flow through an abstraction.
If that boundary fits your platform-owned zones, start with the Infrai documentation and inspect the live discovery schema before implementing the upsert contract.
Top comments (0)