Memory Management

RedAmon runs everything on a single host: the databases (Neo4j and Postgres), the AI agent, the web app, and, on demand, several recon scans. Each scan launches its own set of tool containers (naabu, httpx, katana, nuclei, gau, and so on), so a few parallel scans can add up to a lot of memory very quickly.

The memory governor is the built-in system that watches how much RAM is actually free and automatically keeps the whole stack from running out of memory. It works out of the box, needs no setup, and most operators never have to touch it. This page explains what you will see in the interface, the one concept that commonly confuses people, how many scans you can realistically run, and the settings you can change if you want to tune it for your machine.

Related pages: Running Reconnaissance, Recon Pipeline Workflow, Fireteam, Parallel Specialists, Recon Presets, Rules of Engagement, Troubleshooting.


What it does, in plain terms

  • Caps how many scans run at once so their combined memory can never exceed what your host can give. If you start more scans than fit, the extra ones are refused with a clear message (they are never crashed), and you can run them as soon as a running scan finishes.
  • Gives every container a hard memory limit so one runaway tool is stopped in isolation instead of dragging down your database or the whole app.
  • Turns tool settings down under pressure. When free RAM is low, a scan automatically runs with fewer parallel threads and smaller crawl lists, and it records exactly what it changed.
  • Refuses to start on a host that is too small, with an upfront message, instead of failing in a confusing way later.

Everything is safe by default. If the governor cannot read memory information for any reason, it simply does nothing and RedAmon behaves exactly as it did before the feature existed.


What you will see in the interface

A RAM and CPU meter in the bottom-right of the footer, for example:

RAM ▓▓▓▓░░░ 64%  11.3 GB free    CPU ▓▓░░░░ 12%    v5.3.0

Hover over it for a breakdown, including how much RAM is currently available to start a new scan. The bar updates every few seconds.

A pop-up when a scan cannot start. If you try to launch a scan that will not fit, a modal explains why:

  • "Not enough memory" means it is a RAM limit. The scan will fit once a running scan finishes and releases its memory. You do not need to change anything, just retry shortly, or free up memory by stopping another scan.
  • "Scan limit reached" means you hit a configured ceiling (see RECON_MAX_CONCURRENT_GLOBAL below), not a memory problem. Raise the setting if you want more.

Red lines in the recon logs drawer that begin with [RESOURCE-CAP], for example:

[RESOURCE-CAP] nuclei NUCLEI_CONCURRENCY 25 -> 11 (avail 8.3 GB, ratio)
[RESOURCE-CAP] katana KATANA_PARALLELISM 8 -> 4 (avail 8.3 GB, ratio)

Each line means a tool setting was automatically lowered to fit the memory available when that scan started. The scan still runs and still produces results, it just runs with less parallelism (a little slower, a little less exhaustive). This is normal and expected under load, not an error.

None of these three signals indicate a fault. They are the governor doing its job.


The one concept that confuses people

The footer shows two different RAM numbers on purpose, and they are meant to disagree:

  • … GB free (next to the bar) is the RAM that is physically free right now.
  • "available for a new scan" (in the tooltip) is that free RAM minus the memory your already-running scans have reserved.

Here is why they differ. Suppose you have 11 GB free, but five scans are running and each one reserved about 3.7 GB up front. The governor has already set aside that memory for work in progress, so only about 5.9 GB is actually available to admit a new scan. That is why a scan can be refused even when the bar does not look full.

Think of it like a parking garage: "free spaces" is how many are empty this instant, but "available for a new car" also subtracts the spaces already promised to cars that are still driving in. Free RAM is what you have; "available for a new scan" is what is left after existing work is accounted for.


How many scans can I run at once?

The governor reserves a fixed budget of memory per scan, then admits scans until that budget is used up. In round numbers, on a typical host it works out to roughly:

Host RAMRough concurrent full scans
8 GB1 (often best to run scans one at a time)
16 GB2 to 3
32 GB5 to 6
64 GB12 to 14

These are conservative defaults chosen to keep you safe, not hard technical limits. If your targets are small and your scans are light, you can safely raise the count by telling the governor to reserve less per scan (see Tuning for your host). If a scan is refused, that simply means the budget is full for now, wait for one to finish.

This budget applies across all projects, and it counts every kind of scan: full recon, Partial Recon single-tool runs, Adversarial AI Recon, GVM, GitHub Secret Hunting, and the Secret Multiscanner (which reserves per source: 768 MB by default, 1.5 GB for Docker and Hugging Face, 1.125 GB for S3 and GCS).


How it works with other features

  • Recon Presets and per-tool settings. The values you set in Recon Presets and a project's recon settings are the ceilings. The governor only ever lowers them under memory pressure, never raises them above what you configured. When RAM is plentiful your scans run at exactly the settings you chose.
  • Stealth mode. Stealth already forces low, quiet settings. The governor runs after Stealth, so it can tighten things further under pressure but never loosens what Stealth set.
  • Rules of Engagement. RoE rate caps and time windows are unaffected; the governor manages memory, not request rates or scheduling permissions. Both apply together.
  • Fireteam and the AI agent. The same idea protects the agent: Fireteam member count and the number of tools the agent runs in parallel are scaled down when memory is tight, and the number of simultaneous chat sessions and background jobs is capped. The agent stays responsive instead of exhausting its container.

Common tasks

I want toDo this
Turn the whole feature offset REDAMON_MEM_GOVERNOR=0 in .env, then ./redamon.sh up
Allow or limit how many scans run at onceset RECON_MAX_CONCURRENT_GLOBAL=N (a hard ceiling across all projects). 0 pauses all new scans. Leave it unset to let RAM decide.
Run more scans on a small hostreserve less per scan: lower RECON_JOB_ENVELOPE_MEM, or raise SERVICES_PCT down / OS_RESERVE_PCT down to enlarge the scan pool
Get past a refused boot ("insufficient memory")set REDAMON_SKIP_RAM_GATE=1, or a custom REDAMON_MIN_RAM_MB
Add a cushion so brief spikes do not cause refusalsset REDAMON_ENABLE_ZRAM=1 (native Linux hosts only)
Limit concurrent agent chats or background jobsset MAX_AGENT_SESSIONS or MAX_BACKGROUND_JOBS
Give each tool container more or less memoryset BROKER_TOOL_MEM_BYTES (default: derived from the tool's measured envelope)
Tune the caps to this host by measuring its real usagerun bash tests/redamon_mem_calibrate.sh baseline

After changing any value in .env, apply it with ./redamon.sh up (or ./redamon.sh update). Settings are read at startup, so a running stack does not pick them up until you restart it.


Tuning for your host

You almost never need this, but if you want the governor sized precisely to your machine, run the calibration once. It measures how much memory your services and scans actually use and writes the numbers into a profile the governor then uses in place of its conservative built-in guesses:

bash tests/redamon_mem_calibrate.sh baseline          # measures the always-on services

The profile is specific to your host and is not shared or committed, so each machine measures its own. If you never run it, the safe built-in defaults are used.

Quick manual recipes:

  • Small host (16 GB or less), want more scans: set RECON_JOB_ENVELOPE_MEM=2g (only if your scans are light), and consider REDAMON_ENABLE_ZRAM=1.
  • Large host (64 GB or more), want maximum throughput: leave the defaults, or raise RECON_MAX_CONCURRENT_GLOBAL if you want an explicit higher ceiling.
  • Shared machine, keep RedAmon polite: raise OS_HEADROOM_MEM so more RAM is always left for the rest of the system.

All settings

Every setting is optional; the default shown applies when it is unset. Memory sizes accept 2g, 512m, or a plain number of bytes. The full technical detail lives in the developer reference at docs/readmes/README.MEMORY_GOVERNOR.md.

On or off

VariableDefaultWhen to change it
REDAMON_MEM_GOVERNORonSet 0 or false to disable all dynamic capping (falls back to fixed limits only).

How many scans, sessions, and jobs run at once

VariableDefaultWhen to change it
RECON_MAX_CONCURRENT_GLOBALRAM-decidedHard ceiling on concurrent scans across all projects. 0 pauses all new scans.
MAX_AGENT_SESSIONS20Maximum simultaneous agent chat sessions.
MAX_BACKGROUND_JOBS16Maximum simultaneous background agent jobs.
TERMINAL_MAX_SESSIONS5Maximum Kali terminal sessions.

Small-host tuning (how much RAM is reserved)

VariableDefaultWhen to change it
OS_HEADROOM_MEMcomputed (~8% of RAM)RAM always kept free for the operating system. Written by redamon.sh from your host's size; tune the share with OS_RESERVE_PCT. Lower it to squeeze more work onto a small host; raise it to be a better neighbour on a shared machine.
SERVICE_BASELINE_MEMmeasured, else computed (~60% of usable)RAM assumed for the always-on services. Written by redamon.sh from the same computation that sets the per-service limits, so the scan pool and the service caps can no longer disagree. Lower to allow more scans; raise if your database is heavily loaded.
RECON_JOB_ENVELOPE_MEMmeasured, else 4gRAM reserved per scan. Lower to run more scans at once (only if your scans are light).

Startup check and swap cushion

VariableDefaultWhen to change it
REDAMON_SKIP_RAM_GATEoffSet 1 to boot even when RAM looks insufficient.
REDAMON_MIN_RAM_MBderivedCustom minimum-RAM threshold, in MB, for the startup check.
REDAMON_ENABLE_ZRAMoffSet 1 for a one-time compressed-RAM swap cushion (native Linux only; a no-op on Docker Desktop).
REDAMON_ZRAM_SIZEhalf of RAM, capped at 8 GBExplicit zram device size.

Per-container limits (advanced)

VariableDefaultWhen to change it
BROKER_TOOL_MEM_BYTESderivedMemory cap for each recon tool container (naabu, katana, nuclei, and so on). Defaults to the governor's container_cap() of the measured tool envelope, so a calibrated host uses its own figures; it was a flat 2 GiB that ignored calibration.
NEO4J_MEM, NEO4J_HEAP, NEO4J_PAGECACHEhost-sizedNeo4j container limit and JVM sizing. Change HEAP and NEO4J_MEM together (the container limit must exceed the heap).
AGENT_MEM, POSTGRES_MEM, WEBAPP_MEM, RECON_ORCHESTRATOR_MEM, KALI_MEM, CAPTURE_PROXY_MEM, DOCKER_BROKER_MEM, TRAFFIC_INGEST_MEM, and GVMD_MEM / GVM_OSPD_MEM / GVM_REDIS_MEM / GVM_POSTGRES_MEM / GVM_DATA_MEM with --gvmcomputedPer-service caps, each a share of your host's RAM. Do not set these: they are written into a managed block at the bottom of .env and regenerated on every up, so the allocation re-tunes itself when the host is resized. To pin one, set it anywhere OUTSIDE that block and it is left alone.
OS_RESERVE_PCT, SERVICES_PCT, BURST_FACTOR, BURST_SWAP_MIN_PCT, BLAST_PCT, REDAMON_WEIGHT_*see defaultsThe shares the allocation is derived from. BURST_FACTOR is a request: it is clamped so the worst case can never exceed RAM + swap.
PER_CONTAINER_MAXabout 55% of RAMThe most any single container may use, so one container can never take the whole host.
WEBAPP_DEV_MEM4gAffects dev mode (up dev) only; the dev web server needs much more RAM than production.

Sensitivity tuning (advanced)

VariableDefaultWhen to change it
MEM_SCALE_HIGH0.50Above this free-RAM fraction, tools run at full settings. Raise it to start throttling sooner.
MEM_SCALE_LOW, MEM_SCALE_FLOOR0.15Below this fraction, tools run at their minimum.
MEM_BUDGET_FRACTION0.10Share of free RAM a single crawl list may use.
AGENT_MEM_BUDGET_FRACTION0.5Share of free RAM the agent's parallel work may use.
MEM_SAFETY_TOLERANCE0.25Safety margin (+25%) added on top of measured memory figures.

Troubleshooting

"My seventh scan was refused." Expected. The governor admits as many scans as fit your RAM budget (about six on a 32 GB host) and refuses the rest with a memory message. Wait for a running scan to finish, its reservation is released automatically within about 30 seconds, or free up memory by stopping a scan.

"The bar shows 50% but the tooltip says only 5.9 GB left. Is that wrong?" No. The bar is physical RAM used. The 5.9 GB is what is available to start a new scan after subtracting the memory your running scans reserved. See The one concept that confuses people.

"RedAmon refused to start with an insufficient-memory message." Your host has less RAM than the core services need. Free up memory, raise the Docker VM memory (on Docker Desktop), or set REDAMON_SKIP_RAM_GATE=1 to override the check.

"I see red [RESOURCE-CAP] lines during a scan." That is the governor lowering tool settings to fit the memory that was available when the scan started. The scan still completes; it just runs with less parallelism. If you want full settings, free up RAM before starting the scan, or run fewer scans at once.

"In dev mode the web app will not finish loading, or shows Failed to fetch." Dev-mode compilation needs far more memory than production. Its cap is WEBAPP_DEV_MEM (default 4g); raise it if your machine is very constrained, then ./redamon.sh up dev.

"How do I see current memory usage?" Use the RAM and CPU meter in the bottom-right of the footer. It updates every few seconds and its tooltip shows the full breakdown.

"A scan container was stopped mid-run." If a single tool used far more memory than expected, its container is stopped in isolation (the rest of the scan and the whole stack keep running) and the scan reports that tool as failed. This is the safety limit doing its job; it is rare, and usually means a very large target or an unusual response.