Sizing¶
Two questions matter when sizing a deployment: how many engines (one per host, plus a second for high availability if you need it), and how many concurrent connector sessions per engine. The licensed connector-session count is bundled with each edition — see Editions for the full table.
How to count connector sessions¶
A connector session is one long-lived Defendr session held by one connector helper process. Squid maintains a pool of helpers, sized by the url_rewrite_children directive in squid.conf. The standalone bundle ships with 5 helpers; a busier proxy may run 10–30.
To estimate the count for a new deployment, sum the url_rewrite_children value across every proxy that will connect to a single engine, then add a buffer (we recommend at least 20 %) for traffic growth.
For a Squid deployment on a separate host that forwards to a remote engine, the connector-session count for that host is its own url_rewrite_children value — each connector helper opens one Defendr session to the engine.
Workstation deployments¶
The primary deployment shape — end-user browsing traffic going through the proxy. Each active user generates roughly 5–15 verdicts per second at busy times. The bundled-connector-session counts below assume that traffic profile.
| Deployment shape | Connectors / engine | Recommended edition |
|---|---|---|
| Small office (5–50 users) | 5–10 | Lite (10 bundled) |
| Mid-size office (100–500 users) | 10–25 | Pro (25 bundled) |
| Large deployment (500–1,500 users, 1+ sites) | 25–60 | Enterprise (50 bundled + add-on bundles) |
For redundancy, run an HA pair — one license per engine, each engine carrying its own bundled session count (so an Enterprise HA pair has 50 + 50 = 100 sessions before any add-on bundles).
Server-traffic deployments¶
A secondary deployment shape: filtering HTTPS egress from servers rather than end-user workstations. Common drivers are package updates over HTTPS (apt / yum / pip), API calls to third-party services, audit-required outbound filtering in regulated environments, and supply-chain controls that prove servers can't reach unauthorised hosts.
Servers generate steady automated traffic at roughly 1–5 verdicts per second each (package updates, API calls, telemetry), much lower than the 5–15 of an active user. The same connector budget covers roughly 3–5× more server endpoints than workstation users:
| Edition | Bundled connectors | Workstation users | Server endpoints |
|---|---|---|---|
| Lite | 10 | ~300–500 | ~1,000–2,000 |
| Pro | 25 | ~700–1,500 | ~3,000–5,000 |
| Enterprise | 50+ | 1,500+ | 5,000+ |
A small server fleet (~500 servers) fits comfortably in Lite. A mid-sized server estate (~3,000 servers) fits in Pro. Only very large server fleets reach Enterprise sizing.
The identity-aware portal features (Active Directory on Pro, RADIUS on Enterprise) are largely unused on server-traffic deployments — servers don't have human users to attribute traffic to. For server-side deployments the value of moving up an edition is the operator Web UI (Pro), operator SSO and audit retention (Enterprise), and the bundled support tier — not portal-identity.
Memory sizing¶
The engine container's memory limit is set via ENFORCEGATE_MEMORY in the bundle's .env file. The shipped default is 1g, which fits small deployments (no large domain-list blocklists) but is not enough for deployments loading multi-million-rule blocklists — those will exit with an out-of-memory kill the first time the engine populates its in-memory match structures.
The dominant memory consumer is the set of unique domain hosts the engine matches against. Steady-state memory scales with the total number of compiled rules in the engine database — the sum of every entry across every match-domain-list, every regex, and every literal-URI match block. It does not scale with the number of .policy files.
Recommended limits by rule count¶
| Total rules loaded | Recommended ENFORCEGATE_MEMORY |
|---|---|
| ≤ 100 000 | 512m |
| 100 001 – 1 000 000 | 2g |
| 1 000 001 – 4 000 000 | 4g |
| 4 000 001 – 10 000 000 | 6g |
| 10 000 001 – 20 000 000 | 10g |
| 20 000 001 – 150 000 000 | contact support for sizing — most deployments at this scale fit comfortably under 16g |
EnforceGate vX is engineered to scale to up to 150 million rules per engine — large category-based filtering corpora, multi-million-entry threat-intel domain feeds, and combined allow / deny lists all run on one engine without sharding. Above 150 M rules contact support for sizing assistance.
To read the current loaded rule count from a running engine, use the policy-introspection verb:
> show policy list
…
Total: 47 rules — 3 regexes, 41 domain-list rules, 3 other; 4.6M aggregate domain entries.
The number to look at is the aggregate domain entries plus regex / other rules — that is the count that drives the table above. See show policy list for the full verb reference.
Setting the value¶
Edit the bundle's .env:
Then restart the engine container so Compose re-interpolates the limit:
Verify the limit took effect:
docker inspect enforcegate --format '{{.HostConfig.Memory}}'
# expect a byte count matching your setting — 6442450944 = 6 GiB
Three gotchas worth a checklist line
eghost upandeghost restartread.envfrom the current working directory. If the value doesn't seem to take effect,cdto the bundle directory (/var/lib/enforcegate-hoston the appliance, the directory you unpacked the standalone bundle into on Docker hosts) before invokingeghost.- Do not patch
mem_limit:directly indocker-compose.yml— the installer rewrites the compose file from a template on every upgrade and your manual edit is reverted. SetENFORCEGATE_MEMORYin.envonly. - Upgrades before 2026.21.0 silently reset
.envknobs to the template defaults. Earlier releases re-rendered.envfrom the bundle template on every install / upgrade and only re-applied the wizard's collected fields (license, admin, hostname), reverting any operator-tuned values likeENFORCEGATE_MEMORY. From 2026.21.0 onwards the installer preserves operator-set keys across upgrades. If you're upgrading from a 2026.20.x or earlier release and had a tunedENFORCEGATE_MEMORY, re-check the value in.envafter the upgrade completes; from 2026.21.0+ the value carries over automatically.
Recognising memory exhaustion¶
If the engine container exits unexpectedly during a policy reload or on first boot after a large policy was added, memory exhaustion is the most common cause. Three signals, easiest first:
eghost statusshowsfailed (OOM-killed, raise mem_limit — exit N)in the engine's Services column instead of the genericfailed (exit N). This is the most actionable signal — the message names the fix.-
docker inspectconfirms the kernel sent SIGKILL on memory exhaustion: -
eghost logs enforcegateshows the engine's three boot info lines (license edition, license expiry, captive-portal redirect target) and then nothing. The "silent exit after three info lines" shape is the visual fingerprint of cgroup-OOM during policy load — the kernel sends an uncatchable SIGKILL, so the engine cannot write a fatal log line before dying.
To monitor headroom on a healthy deployment, sample steady-state memory:
docker stats enforcegate --no-stream \
--format 'mem: {{.MemUsage}} ({{.MemPerc}})'
# e.g.: mem: 3.086GiB / 7GiB (44.09%)
A steady-state above ~75 % of ENFORCEGATE_MEMORY means there is no headroom for the transient spikes during policy reloads — bump up to the next row in the recommended-limits table.
Outgrowing your edition¶
If your deployment outgrows its bundled connector count, two paths are available:
- Move up an edition — Lite → Pro or Pro → Enterprise. Replace the license file, restart the engine container, and the upgraded feature surface and higher bundled session count apply on the next boot. See Upgrading your edition.
- Buy capacity add-on bundles — 5-session increments, per engine, at a single flat price across all connector types (Squid today; the same price will apply to future TLS-proxy and ICAP connector types when they ship). Availability depends on your edition — contact sales to discuss the right shape for your deployment.
The license file carries the resulting cap; once it lands on disk the engine reads the new ceiling on its next start.