Build1 distinct publisher3 min readPublished
Two declared reservations totalling 110% of node memory left a task pending in a single-node lab while both containers idled at 480 KiB. Cutting one reservation to 20% released it with nothing else changed.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A reservation is an accounting entry against the node, and the scheduler does that subtraction before it looks at anything the container is doing. On the 5.772 GiB test node, Service A's 3.463 GiB reservation leaves 2.309 GiB that Swarm is still willing to promise [15]. Service B asked for 2.886 GiB [6]. It is short by 0.577 GiB, so the task sits at Pending with "no suitable node (insufficient resources on 1 node)" [15][7]. Runtime consumption is not an input to that comparison. `docker stats` will keep agreeing with you about the 480 KiB for as long as you keep asking it [5][13].
The size of the gap is the part worth carrying around. Service A's reservation is roughly 7,565 times the memory the container actually used [16]. After the fix, the node has 80% of its memory committed while the two lab containers together consume about 960 KiB, on the order of 0.016% of capacity [17]. Both numbers are correct at once, and only one of them decides placement.
What has to be true for this to transfer. The reproduction script derives reservations as percentages of whatever the node reports, so the 110% failure and the 80% success reproduce on a node of any size [3]. The 480 KiB does not transfer: it is a property of an Alpine container sleeping in a loop [2], and your service will idle wherever it idles. If your reservations came from a real measurement rather than a percentage, the arithmetic is unchanged. The number to argue about is still the declared reservation, because that is the only one the filter reads.
Two things in the documentation make this deliberate rather than surprising. `--reserve-memory` is not a runtime cap, and `--limit-memory` is the flag that enforces a maximum a task may consume [10]. And the pending behaviour is documented per node: if no node has enough memory available to satisfy a service's reservation, the task stays pending [11]. My reading of that phrasing is that a reservation is not divisible across hosts, so adding capacity helps only when a single node can hold the whole declared figure. The lab had one node, so it cannot settle that on its own [1].
The failure mode the author points at is the one that costs real money. If infrastructure scaling and workload scheduling read different signals, an external autoscaler whose scale-out rule watches host CPU utilization and host runtime memory sees a quiet host [14]. The scheduler, meanwhile, is refusing work on commitments nobody is using. Nothing scales out, and nothing gets placed. Fixing it took one reservation change from 50% to 20%, with no memory added, no node added, no daemon restart, and no change to the application [8][9].
Ranked by verification strength, evidence, and original report placement.
The author built a disposable single-node Docker Swarm lab with Docker client 29.4.3, Docker server 29.2.1, 4 CPUs and node memory of 5.772 GiB, with no existing Swarm services.
The workload used in the lab was an Alpine container sleeping in a loop, described by the author as deliberately boring.
For portability the reproduction script calculates reservation sizes from whatever memory the Swarm node reports: Service A 60%, Service B 50% initially and 20% after the update, so the first placement attempt asks for 110% of node memory and the second for 80%.
On the 5.772 GiB node, Service A received a reservation of 3.463 GiB and Swarm scheduled it successfully, showing swarm-reservation-a 1/1.
Runtime stats for the scheduled service reported MemoryUsage=480KiB / 5.772GiB, MemoryPercent=0.01% and CPU=0.00%.
Service B was created with a reservation equal to 50% of node memory, or 2.886 GiB, taking combined reservations to about 6.349 GiB against a node capacity of 5.772 GiB.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 27, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
912MB to 108MB is mostly typing now, and that weakens the base-image excuse in review1 distinct publisher
build
A container is five namespaces, a root filesystem swap, and two writes to cgroupfs1 distinct publisher
build
Before you spend quota on an agent skill, make it pass an eval harness1 distinct publisher
build
The merge gate that turns "works on bad networks" into something CI can fail1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Reproducible lab, documented mechanism, one self-reported run
The mechanism is demonstrated end to end with exact versions, reservation arithmetic, and before/after command output, and it is corroborated by Docker's own documented behaviour that a task stays pending when no node can satisfy its reservation. Evidence is capped below high confidence because everything comes from one self-authored source, on a single node, with no independent replication.
No adoption or field-usage data
The only observation is the author's own lab run. The cluster contains no deployment counts, production incident reports, usage disclosures or third-party reproductions, so real-world adoption of this practice or the frequency of the failure mode cannot be measured.
Claims sit at or slightly below the evidence
The headline result matches exactly what the lab shows, the mechanism is documented vendor behaviour rather than a discovery, and the author explicitly caveats that the autoscaler scenario is an implication rather than a tested result. If anything the operational significance of the reservation-versus-utilization divergence is stated more cautiously than the demonstration would support.
Low commercial incentive, some author-visibility incentive
The single source is a personal developer-platform post with no vendor sponsorship, product pitch, pricing or competitive claim; the author documents behaviour that Docker itself publishes. The residual incentive is reputational: a packaged public lab and a striking 480 KiB headline reward attention, which favours a surprising framing of documented behaviour.
Mechanism solid, breadth unproven
Confidence is high that the demonstrated behaviour is real and correctly explained, because it is reproducible and matches documented Swarm semantics. It is limited by a single publisher, a single-node lab, no CPU-reservation or multi-node testing, and no evidence about how often this bites real deployments.