Skip to content

Config schema: pools

This page lists the fields for the top-level pools: list and each pool / backend object. For behavior — selection, weights, multiple pools, retries — see Pools and backends.

pools

Property Value
Type List of pool objects
Required Yes for a runnable installation (forwarding needs at least one pool with backends)
Location Top-level key in the config file

Each list entry is one named pool. Pool name values must be unique within the file; duplicate names fail validation.

Pool object

FieldTypeRequiredDefaultDescription
namestringyes—Identifier referenced by set_pool, set_retry_pool, Rhai set_pool / set_retry_pool, metrics labels, and event filters. Must be non-empty and unique among pools. The name default is a convention for the catch-all pool when nothing else selects a pool — see Default pool selection.
backendslistyes—One or more backend entries. An empty list fails validation.
healthobjectno(disabled)Optional backend health settings for this pool. See Reference: health.
sources_v4list of stringsno(use forward defaults)IPv4 addresses to bind when forwarding to this pool’s backends. Overrides global forward.sources_v4 for this pool when non-empty. See Dual-stack forwarding.
sources_v6list of stringsno(use forward defaults)IPv6 addresses for upstream egress for this pool. Overrides global forward.sources_v6 when non-empty.
max_inflightintegerno(unlimited)Optional cap on concurrent in-flight forwards for this pool. When set, must be ≥ 1. Enforced under the split_io runtime; a query that would exceed the cap returns SERVFAIL rather than queueing. See Per-pool in-flight limit.

Default pool selection

When no rule, Rhai script, or retry has set a pool for the transaction, Conduit picks a pool at Route time:

  1. If a pool named default exists, use it.
  2. Otherwise use the first pool in the pools: list (YAML order).

Naming a catch-all pool default is a convention, not a schema requirement — validation does not require that name. If you omit default, list order defines the fallback pool. A pool named default that appears later in the list still wins over earlier pools when fallback applies.

For examples (split horizon, explicit rules vs catch-all), see Pools and backends.

Pool sources_v4 / sources_v6 constraints

  • Each entry must be a valid IPv4 or IPv6 address (not ip:port).
  • Entries must not be empty strings.
  • At most 32 addresses per list (sources_v4 and sources_v6 separately).
  • When a pool list is empty or omitted, Conduit uses the corresponding global forward.sources_v4 or forward.sources_v6 list (if any), then system defaults for bind behavior.

Per-pool in-flight limit

max_inflight bounds how many transactions may be forwarding to this pool at once. It is a coarse pool-level guard — distinct from per-backend upstream concurrency (forward.outstanding_per_backend) and the global transaction slot pool (orchestrator.txn_table_capacity).

  • Default (unset) — no per-pool cap; pool concurrency is bounded only by the slot pool and per-backend limits.
  • Set — when a forward would exceed the cap, Conduit returns SERVFAIL to the client immediately (it does not queue or block). The reserved slot is released when the upstream replies, times out, or errors.
  • Runtime scope — enforced under the split_io runtime. Under sync, pool concurrency is already bounded by listener threads, so max_inflight is validated but not separately enforced.

Backend object

Backends are nested under pools[].backends. Each backend is one upstream resolver. An optional name gives the backend a stable identity for metrics labels and control-plane overlay patches; without it the upstream is identified by address.

Field Type Required Default Description
address string yes — Upstream resolver as ip:port. IPv6 literals use bracket notation, for example [2001:db8::1]:53. Must parse as a socket address.
weight integer no 100 Load-balancing weight within the pool. If set, must be ≥ 1. Omitted or unset means effective weight 100.
name string no (use address) Stable identity for this backend. When set, it becomes the backend metric label and the key for overlay patches that target (pool, name). Must be unique within the pool when set.
probe_qname string no (pool health template) Per-backend override for health probe query name when pool health is enabled.
probe_qtype string no (pool health template) Per-backend override for health probe query type.
probe_source string no (system bind) Local IP address to bind for health probes to this backend.
transport string no — Reserved for forward-compatible use; not honored when it diverges from forward.upstream_transport.

Validation summary

Rule Error if violated
Unique pool name duplicate pool name '…'
Non-empty pool name pool name must not be empty
Pool has ≥ 1 backend pool '…' has no backends
Backend address parses pool '…' backend '…': invalid socket address
Backend weight ≥ 1 when set pool '…' backend '…' weight must be >= 1
Backend name unique within a pool pool '…' duplicate backend name '…'
Pool max_inflight ≥ 1 when set pool '…' max_inflight must be >= 1 when set
Valid pool sources_v4 / sources_v6 pool '…': … (parse/limit messages)

Validate with conduitctl validate --file … or load via the running process; see Config file.

Reload and restart

Pool routing — backend address, weight, name, pool membership, and sources_v4 / sources_v6 — is hot: a successful reload applies to new queries from the next snapshot, and metric labels follow the new name values.

max_inflight is fixed at process start. A changed value is stored in the new snapshot but the active limit is not re-read until you restart conduit.

Example configuration

pools:
  - name: default
    sources_v4:
      - "10.0.0.10"   # Conduit host on the recursor-facing VLAN
    backends:
      - address: "10.0.0.1:53"
        name: resolver-a   # stable metrics label + overlay target
        weight: 70
      - address: "10.0.0.2:53"
        name: resolver-b
        # weight omitted → 100
  - name: internal
    max_inflight: 256       # cap concurrent forwards to this pool (split_io)
    sources_v4:
      - "10.0.1.10"   # Conduit host on the internal DNS network
    backends:
      - address: "10.0.1.53:53"