• v0.0.13
    Gates / frontend (push) Successful in 1m35s
    Gates / test (push) Successful in 2m23s
    Gates / test-aarch64 (push) Successful in 8m13s
    Gates / package (push) Successful in 4m15s
    Gates / container (push) Successful in 10s
    CI / gates (push) Successful in 23m19s
    Release / guard (push) Successful in 34s
    Gates / frontend (push) Successful in 1m39s
    Gates / test (push) Successful in 2m19s
    Gates / test-aarch64 (push) Successful in 7m25s
    Gates / package (push) Successful in 48s
    Release / publish (push) Successful in 6m36s
    Gates / container (push) Successful in 17s
    Release / gates (push) Successful in 10m52s
    Stable

    mokhtar released this 2026-08-27 20:36:04 +00:00 | 0 commits to master since this release

    The upstream query budget becomes one honest deadline. A busy network no longer blames a healthy standby for running out of time, and a query burst no longer queues invisibly until everything answers SERVFAIL at once.

    Fixed

    • The per-query upstream budget is now one absolute deadline, spent by everything that blocks. Waiting for a free slot on a saturated upstream now spends the query's upstream.total_timeout_ms budget just like the exchange itself, instead of being invisible to it — under a burst, queries used to wait out their whole budget in the queue and then start attempts they could never finish. An attempt near the end of the budget runs truncated, and when a truncated attempt runs out of time that is evidence about the budget, not the upstream: it no longer counts against that upstream's health or success rate, and the query log no longer names an upstream that was given no fair chance. A field incident produced 279 rows blaming a standby whose health counters read zero for zero; those rows now attribute nothing.
    • A query no longer blocks behind a saturated upstream while another has capacity. Admission sweeps the upstreams in priority order and takes the first free slot; priority now means the order among upstreams that can be admitted right now, and a query blocks only when nothing has capacity — on the highest-priority eligible upstream, bounded by the remaining budget.
    • Conditional forward zones spend upstream.read_timeout_ms once per query. A UDP attempt, a truncated answer and the TCP retry now share the one budget instead of taking a fresh one each, so a slow zone resolver can no longer stretch a single query to several times the configured timeout.

    Added

    • nxdns_upstream_budget_exhausted_total. A pool-wide counter of queries whose budget ran out — in the queue or mid-attempt — before any upstream answered. It carries no per-upstream label on purpose: running out of budget is a fact about the pool.
    • A configuration with more than 64 enabled upstreams is rejected at validation with a clear message, instead of tripping an internal limit at startup.

    Artifacts

    fa71dca32187e7604de0c7db5c2b710b99a26d5072b5ddd6b10d46ba4f8d6976  nxdns-0.0.13-x86_64-linux-musl.tar.gz
    e821383e483f351ee8e70a2d6d271c6737c0ea7dfa9b3723270a67ee6747fe60  nxdns-0.0.13-aarch64-linux-musl.tar.gz
    9130dacb4c4be48ed1a981fd32f4f9622a1d04b97fe4862c64413dc299df32b7  IMAGE-DIGEST.txt
    
    git.mial.net/mokhtar/nxdns:0.0.13@sha256:567fa7e1e0f92c0d4d92e756a0043e5be0ee3442e08cad6e340be489f6912ce0
    

    Compare v0.0.12...v0.0.13

    Commits since v0.0.12
    c9701fa build: bump version to 0.0.13
    a3aa7fe upstream: one absolute per-query budget across queueing and failover
    
    Downloads