Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Performance model

NXD’s performance rules are mostly about not doing work. Two ideas carry almost all of it: evaluate only what was selected, and let independent work proceed independently.

Select first, then evaluate

Nix evaluation is the expensive part of any deployment tool. The naive approach evaluates the whole site and filters afterwards, so planning gets slower with every host added, whether or not you touched them.

NXD selects before it works. Planning one target evaluates that target’s systems, its providers, and its secret bindings. It does not:

  • evaluate unrelated hosts to discover they were not selected;
  • observe endpoints belonging to resources outside the selection;
  • recursively hash or enumerate closures to prove equality; or
  • resolve secrets for hosts that are not part of the operation.

The practical consequence is that planning cost tracks what you asked for rather than how large the site has become.

Related invariants:

  • The selected canonical site is evaluated once per command, and its JSON is parsed once.
  • Exact-target projections are used only when they are semantically equal to the selected slice of the full site. A broad selector falls back to the full site and then deterministic selection, rather than an unsafe partial projection.
  • Selected output evaluation is batched where practical.

Independent work runs concurrently

The scheduler starts an action as soon as its own dependencies have succeeded and no conflicting resource is locked. It does not wait for artificial batch waves, so fast work never idles behind slow, unrelated work.

This matters most across mixed fleets. A Proxmox guest, a cloud droplet, and a Darwin host share no dependencies and no ownership locks, so they progress in parallel while the ordering that genuinely matters is still enforced.

Concurrency is bounded by --parallel (default 5).

Two rules keep this safe:

  • Only actions whose complete dependency set succeeded may start. If a prerequisite fails, its dependants remain unexecuted rather than being reported as provider failures.
  • The scheduler acquires ownership locks for conflicting resources, so concurrency never lets two actions mutate the same thing.

Connections are reused, observations are not

Authenticated transport connections are reused within an operation, which removes a per-command handshake. See transport.

Observations are deliberately not reused. NXD never carries an observation across observe, apply, verify, endpoint identity, credential, reviewed configuration, or process boundaries. Caching live state would make a plan depend on stale information, which is exactly the failure mode digest-bound approval exists to prevent.

For the same reason, NXD prefers Nix’s own store and substitution behavior over maintaining custom caches or artifact registries.

Delivery takes one route

Each reviewed output is bound to a single delivery route. Builder-direct install and conversion batch system, Disko, and kexec inspection over one connection.

When substituteOnDestination is enabled (the default), the destination fetches what it needs from its own configured signed cache, and the reviewed builder is a lower-priority trusted source for exact reviewed paths missing from that cache. The closure is never routed through the orchestrator as an intermediary.

Measuring it

--profile reports per-phase timings. See output and logs.

For the complete invariant list and route composition table, see docs/architecture-design/performance-and-profiling.md in the repository.