# `Hyper.Node.Budget.Soft`
[🔗](https://github.com/harmont-dev/hyper/blob/main/lib/hyper/node/budget/soft.ex#L1)

Soft per-node admission check. Where `Hyper.Node.Budget.Hard` tracks memory and
disk reserved from VM specs, `Soft` holds no state: it answers, from this node's
*live* resource monitors (`Sys.Mon`), whether the machine currently has the
instantaneous headroom to take on another VM.

The soft metrics are the ones whose overcommitment degrades speed rather than
correctness: CPU utilization, disk bandwidth, and network bandwidth. For each,
the node carries a load ceiling in `Hyper.Cfg.Budget` (e.g. "never
schedule onto a machine already past 80% CPU"). A spec is admissible only if the
measured load plus the spec's nominal demand stays under that ceiling on every
metric.

This is purely the instantaneous load filter; it does not model per-VM
reservations or node overcommit, which are `Hard`'s concern.

# `can_run`

```elixir
@spec can_run(Hyper.Vm.Instance.Spec.t()) :: :ok | {:error, term()}
```

Does this node's current measured load leave room to run `spec`?

`:ok` if every soft metric stays under its load ceiling once `spec`'s demand is
added, otherwise `{:error, reason}` naming the first saturated metric.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
