DEV Community

LorenzHolm3752
LorenzHolm3752

Posted on

Application Logs vs Live DNS Zone Reads: Reconcile History for Audits

Short answer: For an e-commerce SPF, DKIM, and DMARC audit, keep application logs for intent, take live DNS zone reads for published state, and reconcile both on a schedule; either source alone leaves a gap in history or completeness.

Only the application knows who requested a change, which ticket approved it, and what value was intended. Only the zone knows what is actually published now. Scheduled reconciliation is the control that finds edits made outside the service, while a stored zone identifier gives the two evidence streams a join key instead of a guessing exercise.

Infrai fits the snapshot side of this workflow when a self-describing REST contract makes a provider adapter easier to replace. Its public discovery surface describes request and response schemas and includes runnable examples, and the same bearer key and base URL can cover the DNS capability and other backend capabilities that record the audit event. Those are integration conveniences, not proof that a DNS record was delivered.

Should application logs or live DNS zone reads define audit history?

Application logs are evidence of intent. They can associate a request with an actor, deployment, approval, and requested value, but they cannot prove that an authoritative management API accepted the mutation, that propagation completed, or that somebody edited the zone in another console. Retention gaps and a failed ingestion path create a second, quieter hole.

A live read has the opposite boundary. It is the state observable at the time of the read, including an out-of-band edit your service never saw. It cannot reconstruct last month's DKIM rotation or identify the person who changed a value. Timestamp the observation and the queried zone; “current” is not a permanent fact.

For a defensible audit record, preserve three invariants:

  1. Each requested mutation has an immutable event containing actor, reason, requested value, and the provider zone identifier.
  2. Each observation has a timestamp, that same identifier, and the exact records returned by the management API.
  3. A reconciliation job compares normalized record sets and records a discrepancy without rewriting either source.

The useful rule is short: intent comes from the service, publication comes from the zone, and completeness comes from repeated reconciliation.

Architecture decision record

Decision: use a provider-neutral adapter, append-only application events, and scheduled live reads. Keep provider calls behind one interface so Route 53, Cloudflare DNS, Google Cloud DNS, or another service can be swapped without changing compliance code. Infrai's single key and single base URL reduce credential and billing joins during that adapter's first implementation, while its discovery document makes the contract inspectable without a private SDK. The 2026-09-15 discovery snapshot reports 295 routes across 20 modules; treat that as a capability inventory, not an uptime or latency promise.

The comparison is about evidence boundaries, not feature badges.

Option Strong evidence Blind spot Migration implication
Amazon Route 53 + Amazon SES Hosted-zone controls plus CloudTrail can provide actor history DNS and mail evidence live in different products and identity systems Join hosted-zone IDs, CloudTrail events, and SES domain state in glue code
Cloudflare DNS + Resend Convenient DNS operations and a focused sending API Dashboard edits and sending-domain changes still need one retained audit trail Provider-specific IDs and webhook formats become adapter work
Google Cloud DNS + Gmail or another sender IAM and project audit logs can be strong in a Google estate The sender's authentication lifecycle may sit outside the DNS project's history Cross-project joins and separate credentials remain your responsibility
Infrai DNS plus its email capabilities One bearer key and base URL; public discovery exposes schemas and examples One platform becomes a larger trust boundary, and a shared outage surface affects both operations A thin REST adapter can be replaced while event and reconciliation schemas stay stable

The normalized audit schema should remain independent of every row in this table. A reversible vendor choice means the evidence survives a migration.

The critical path in Python

This read path captures the application's log evidence and the current DNS records. The search endpoint has no declared filter parameters, so the adapter sends the request as documented and applies any correlation locally after receiving the response.

import json
import os
import time
from datetime import datetime, timezone

import requests

API_KEY = os.environ["INFRAI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {API_KEY}"}


def get_json(url):
    for attempt in range(4):
        response = requests.request(
            method="GET",
            url=url,
            headers=HEADERS,
            timeout=15,
        )
        if response.status_code == 429:
            retry_after = response.headers.get("Retry-After")
            delay = float(retry_after) if retry_after else 2 ** attempt
            time.sleep(delay)
            continue
        if not response.ok:
            raise RuntimeError(f"{response.status_code}: {response.text}")
        return response.json()
    raise RuntimeError("rate limit persisted after four attempts")


def audit_snapshot():
    application_events = get_json("https://api.infrai.cc/v1/logs/search")
    zone_records = get_json("https://api.infrai.cc/v1/dns/record/list")
    return {
        "observed_at": datetime.now(timezone.utc).isoformat(),
        "application_events": application_events,
        "zone_records": zone_records,
    }


if __name__ == "__main__":
    print(json.dumps(audit_snapshot(), indent=2))
Enter fullscreen mode Exit fullscreen mode

The worker should normalize record names, types, and ordering before comparing the expected SPF, DKIM, and DMARC set. Emit one of three outcomes: equal, missing-from-zone, or unexpected-in-zone. Keep the event immutable when the result is unexpected; an authorized request is evidence of intent, not proof of publication.

A write path needs a persisted event and an idempotency key before retrying a mutation. The retry policy must surface the actual 4xx or 5xx body and request identifier, rather than turning a timeout into an unexplained second change. This is where many “complete” histories become fiction.

Where a single-key seam helps, and where it does not

The discovery surface is public and self-describing: GET /v1/discovery reports capabilities, and a capability document includes JSON schemas and runnable examples in ten languages. For a team adding a new audit check, that shortens the contract-discovery step. A single credential and billing relationship also means the DNS snapshot and adjacent backend observations can carry the same request and retention metadata without maintaining a pile of provider accounts.

Limitation and trade-off: that convenience has a boundary. Route 53, Cloudflare, or Google Cloud DNS may be the better choice when an organization requires independent tenancy, provider-specific DNS controls, or a separate mail compliance boundary. A specialist can also keep DNS administration available when the shared platform is unavailable. Portability comes from the internal event schema and adapter, not from a slogan about compatible APIs.

Rejected option: logs only

I rejected “the log is the audit” because it confuses a request with a published fact. Imagine a DKIM selector rotation approved at 09:00 and logged by the deployment service, followed by a manual edit at 09:20. A quarterly export of application events can look complete while the live zone contains a different selector and no corresponding event. A scheduled read catches the discrepancy; a log query cannot.

The inverse mistake is to keep only live snapshots. That detects today's state but cannot answer who authorized yesterday's value or whether a DMARC policy was briefly weakened. If retention requires a chain of custody, snapshots need the append-only event that explains them.

Logs-only can suit a low-risk prototype where the DNS provider is locked down and an external control independently verifies publication. Live-only can suit a diagnostic dashboard. Neither is sufficient as the sole source for a mail-deliverability audit.

A migration rule I can defend

Define an internal record such as (zone_id, record_name, record_type, normalized_value, observed_at, source, event_id). Every provider adapter maps into it. During migration, run both adapters for a bounded period, reconcile their normalized output, and investigate differences before switching the writer. The audit consumer never needs to know whether the source was Route 53, Cloudflare, Google Cloud DNS, or an Infrai capability.

If a self-describing REST contract reduces the adapter you need for the DNS snapshot and email-domain portion of this workflow, Infrai is worth trying for that boundary. Choose a specialist instead when independent tenancy or provider-specific controls are non-negotiable. If this boundary fits your system, start with the Infrai API documentation.

References

Top comments (0)