Gardience Documentation gardience.com →
Docs / Enterprise

Sizing and scale results

What to give the Gardience server, and what we have and have not measured.

Install with --fleet-size N so the Salt master is tuned for the fleet (worker threads, key cache, file and connection limits). Every row is an estimate until the real-agent numbers below are filled in for that size.

Managed nodesvCPUMemoryDisk (data volume)--fleet-size
up to 1,00048 GB40 GB1000
1,000 to 5,000816 GB100 GB5000
5,000 to 10,0001632 GB200 GB10000
over 10,000talk to us first

Linux host with Docker 24 or newer, amd64 or arm64. Disk grows mainly with the audit log and run history. Routine read-only work (scans every 5 minutes, drift checks every 30) is logged with a node count and a SHA-256 of the node list, about 1 KB per job whatever the fleet size: roughly 2 to 5 MB a day. Changes keep every node's name: about 25 bytes per node, so a patch run on 10,000 nodes adds about 250 KB. A 10,000-node fleet patched weekly grows the log by well under 1 GB a year. Segments are sealed at 50 MB; there is no automated retention.

What has been measured

Gardience service, synthetic fleet (tools/tests/scale/run.sh 1000 5000 10000, 200,000-entry audit log):

Measure1,000 nodes5,000 nodes10,000 nodes
Dashboard page (paged, 200 per page, needs-attention first)under 100 msunder 100 ms83 ms, 152 KB
Full compliance data (JSON API)57 ms362 ms598 ms
Reports page3 ms3 msunder 60 ms
Evidence pack (zip, includes a full audit verification)under 6 sunder 6 s4.9 s
Permission check across every Linux node1 ms4 ms5 ms
5 jobs' results from every Linux node ingested3 ms39 ms33 ms
Full audit chain verification, 200,000 entries3 to 4 ssame3.1 s
Audit writes (flushed to disk in 200 ms batches)about 44,000 entries/ssamesame

Every console page and API read stays under 2 seconds at 10,000 nodes except the evidence export (under 5 s).

Real agents, lab (tools/tests/stress/stress.py): 23 real agents (Linux containers plus Windows 11 and Rocky 9 VMs). Full scan in 24 seconds; 15 new nodes joined in 5 seconds; 10 console runs at once all succeeded; agents reconnected within 27 seconds of a Salt master restart; Gardience used 52 MB of memory afterwards.

Real agents, larger runs (tools/tests/scale/agents.sh: separate, unmodified salt-minion daemons, each with its own keys and connection; every run keeps its own log under ~/.gardience-test-all/). Kept results:

Real agents, 1,002 nodes on AWS (2026-10-17, logs under ~/.gardience-test-all/aws/). Server: one m7g.xlarge (4 vCPU, 16 GB), installed from the release bundle. Agents, each an unmodified salt-minion daemon with its own keys and connection: 40 Ubuntu 24.04 VMs (5 on Salt 3006.28, 5 on 3007.15, 30 on 3008.3), 10 Windows Server 2022 VMs, and 952 more Ubuntu agents on 8 shared hosts. Results:

Signed 1.2.4 on the same 1,002-agent fleet (2026-10-18, ~/.gardience-test-all/aws/change-campaign-0221.log and e2e-1.2.4-0224.log). The server was upgraded in place to the signed 1.2.4 bundle (doctor clean, 1,002 agents back).

Governed change on 4,977 real agents (2026-10-18, 1.2.5 plus the 1.3.0 service; ~/.gardience-test-all/aws/ governed-campaign-1510.log, scan5k-watch.log). Server: one m7g.2xlarge installed with --fleet-size 5000; agents: 4,977 unmodified salt-minion 3008.3 daemons, 625 per r7g.2xlarge host. The path a team or an AI agent uses, not an admin shortcut: a non-admin requester's operate key, narrowed to one runbook and one node group, previewed (4,977 nodes) and requested a hosts-file change; the request waited for approval; the requester's own key could not approve it; an admin's approve key did. Gardience ran it under its scoped automation identity and reported success after 166 s; asked directly on the Salt master afterwards, 4,977 of 4,977 agents held the change. The console answered in 134 ms (median) throughout. The job is in the audit log and the chain verifies. During the run salt-api's event stream dropped events and the job-cache reconciler added 186 jobs to the audit log that would otherwise be missing. A full fleet scan then listed all 4,977 nodes after 4 minutes, 4,960 fully scored and the rest filling in as their checks finished (625 agents per host share each host's CPU; real machines answer faster).

This run found and fixed four scale bugs before 1.3.0: AI tool results over 60,000 characters were cut mid-JSON (preview of 4,977 nodes); run status returned every node's result and no longer fit; scans gave up on answers the event stream had dropped instead of asking the master; and a first scan of a large fleet left late nodes invisible until the next scan.

Audit completeness under an event flood (2026-10-18, tools/tests/scale/audit-flood/). Job starts and returns fired on the master's own event bus at 4,000 to 4,600 events a second: 5 jobs of 20,000 nodes, then 4 jobs of 50,000 nodes (200,000 returns). The master's bus carried every event; salt-api's stream, which Gardience reads live, delivered as little as 1 of 5 job starts. With the job-cache reconciler every job was in the audit log within 49 s, no duplicates, audit chain intact, console answering in 5 ms.

Compatibility matrix on AWS (2026-10-18, ~/.gardience-test-all/aws/matrix-results*.json and matrix-run*.out). 42 VMs, one per operating system and Salt agent version: Windows Server 2016, 2019, 2022 and 2025; Ubuntu 20.04, 22.04 and 24.04; Debian 11 and 12; RHEL 9; Rocky 8 and 9; SUSE 15 SP6; Amazon Linux 2023; each with Salt 3006.28, 3007.15 and 3008.3. Every check through the product: health, scan, baseline applied, patch, reboot and reconnect, inventory. The final run (1.2.5 code) passed every check on all 42 (RHEL 9 VMs installed 275 real updates including a kernel, rebooted and came back; baseline 43 to 100). Earlier runs found six bugs, all fixed in 1.2.5: the SSH baseline check could not read settings on Ubuntu 24.04 (SSH started on demand) and the SSH fix did nothing on Rocky 8 (no drop-in folder); turning on the firewall cut the agent off for about 5 minutes on RHEL, Rocky, SUSE, Debian and Amazon Linux (the master's connection is now allowed before the firewall starts); a released held run lost its result and could look finished while patching continued (a reboot then interrupted a kernel install); Debian 11 could not be enrolled (Salt's bootstrap refuses end-of-life releases); and agent restarts and reboots Gardience schedules now wait for any running package manager (a restart mid-patch left two test VMs unbootable).

Real patching at scale: 1,020 independent Windows and Linux machines, governed (2026-10-25, Gardience 1.10.0 release candidate, tools/tests/aws/fleet-1000.sh and patch-campaign.py, evidence in docs/enterprise/evidence/fleet-1020-2026-10-25/). 1,000 Amazon Linux 2023 machines (t4g.nano) and 20 Windows Server 2022 machines (t3.medium), one server (c7g.2xlarge), installed from the bundle with the license. All 1,020 joined through one enrollment with no manual approval. Before, straight from the master: 1,020 answered, 64,000 updates pending (64 per Linux machine, including a kernel). A non-admin operator requested the patch; their own approval was refused; a second person approved it. Patch: 1,020 of 1,020 ok in 804 s, 0 failed, each machine's result in the audit chain. Reboot (requested and approved the same way): 1,020 of 1,020 answering again 237 s after the request. After: 1,020 fully patched, 0 updates pending, every Linux machine on the new kernel; the STIG/CIS-aligned baseline then passed on all 1,020. The signed evidence pack verifies (220 audit entries, 2,040 per-machine outcomes, all ok).

Earlier run: 600 independent machines, governed (2026-10-19, signed Gardience 1.3.0, tools/tests/aws/patch-fleet-launch.sh and patch-campaign.py, ~/.gardience-test-all/aws/patch600/). 600 separate EC2 machines (t4g.nano, 512 MB, each its own kernel, disk and package manager, spread over five availability zones, no public addresses) from a July 2026 Amazon Linux 2023 image, joined through an enrollment token. Before, straight from the master: 600 machines, 82,800 updates pending (138 each, including a kernel), all on kernel 6.1.176. A non-admin's operate key narrowed to the patch, reboot and health-check runbooks and one group requested the patch; its own approval was refused; a second person's approve key approved it. Patch: success after 168 s, 600 of 600 ok. Reboot (requested and approved the same way): success after 77 s, 600 of 600 restarted and reconnected. After, straight from the master: 600 of 600 fully patched, 0 updates pending, all 600 on kernel 6.1.188. The audit chain holds one job.results entry per change naming all 600 nodes as ok (requested by the non-admin), and verifies intact. Test-environment note: the machines had no internet, so the Salt package repository the agent installer had added was disabled on them before the run (updates came from Amazon's in-region repository), as on any private network.

Mixed fleet from the console: 634 machines, Windows and Linux (2026-10-19, the run behind the fleet images on gardience.com; evidence in docs/enterprise/evidence/fleet-634-2026-10-19/). 600 Linux machines (t4g.micro, 1 GB) and 34 Windows Server 2022 machines (t3.medium, 4 GB) on one server, about 70,000 updates pending. Patched from the console in about 15 minutes; the console's own counts, sampled each minute, reached 633 of 634 with 117 updates left, and the last machine was finished with the Fix action: 634 of 634 patched, 0 pending (console screenshot). Not kept: the server's audit log and run records (the server was deleted after the run); the 600-machine run above has them.

Real patching on machines with real updates waiting (2026-10-17, Gardience 1.2.2 candidate, ~/.gardience-test-all/aws/patch-real-.log). Ubuntu 24.04 VMs from a six-month-old image: 4 fresh VMs with 676 updates pending (169 each) were patched, rebooted and rescanned through Gardience in one round: patch 147 s, reboot and all back 43 s, then 4 of 4 fully patched with 0 updates pending. Windows Server 2022 VMs from a three-month-old image (4 VMs, 16 updates pending, including the October cumulative and .NET updates): every update installed through Gardience except one Windows Recovery Environment update (KB5131594), which Windows Update reported as installed successfully three times and still offered again after reboots, a known behavior of those updates when the recovery environment sits inside the OS partition; Gardience reports it as still pending, as Windows does. The cumulative update took about 33 minutes on a 2-vCPU VM. No kept log shows a Windows VM reaching fully patched: the 4 old-image VMs ended with 4 updates pending after 3 rounds (patch-real-windows-.log), and the baseline log records the 10 current-image VMs as 0 of 10 fully patched. These Windows runs overlapped a second test script by mistake, so their logs are not a clean single run.

Salt master restart with the whole fleet busy (every agent running a job, a full scan started, then the master restarted): all 1,018 agents (66 VMs, 952 shared-host agents) answering again within 30 s and through the next 9 minutes (restart-under-load-final.log). The agent hang seen once earlier (during a 990-node patch run that saturated the shared hosts' CPUs) did not recur, so the agents' self-recovery settings were not exercised by this run.

Problems this test found, all fixed. Tests cover the offline check, session handling and the hardening build check; the agent self-recovery and the Debian baseline fix were verified on the AWS machines only:

What has not been measured yet

Not supported yet

Gardience by Bouziden Management LLC.