A sudden Fail2ban memory increase is usually caused by retained state rather than by the act of blocking one address. A very large ban list, long or permanent bans, recidive jails, an oversized SQLite database, repeated replay of systemd journal entries, or firewall/kernel objects can all contribute. Fail2ban has no published universal memory limit or memory-per-ban ratio. Historical reports describe roughly 500,000–1,000,000 banned addresses in one incident and about 2.4 GB of process memory in another, but those figures are incident reports, not capacity guarantees.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
Measure which component is growing before deleting bans or restarting services. The process RSS, Fail2ban’s active-ban count, its SQLite file, the journal, firewall sets/rules, and kernel tables are separate resource pools and require different fixes.
As an Amazon Associate I earn from qualifying purchases.
What can make Fail2ban use so much memory?
Fail2ban reads authentication or service logs, tracks matches in each jail, stores ban state, and asks a firewall action to enforce the decision. An attack can enlarge several of those states at once. The Python process may grow, while the firewall or kernel grows independently; looking only at a system monitor’s total memory can therefore lead to the wrong remedy.
A large active ban population
Every active ban has to be represented in Fail2ban and usually in the selected firewall implementation. The project’s issue #2118 describes extreme memory usage while maintaining approximately 500,000 to 1,000,000 banned IPs. Issue #2045 contains a report of about 2.4 GB of memory on one machine. Neither issue establishes a safe limit: the cost varies with the Fail2ban release, Python runtime, jail count, action, firewall backend, address format, and database workload.
#1 Best Overall
Retention settings that never let state shrink
A long bantime keeps addresses active for longer. Permanent bans, very large values, and recidive jails can retain addresses far beyond the original incident. Multiple jails may also record the same source independently. findtime controls the window in which failures are counted, while maxretry controls how many matches are allowed in that window; these settings affect how quickly new bans are created, not just how long they remain.
Database and match history
Fail2ban uses a SQLite database for persistent state and, depending on configuration, records failure history. A growing /var/lib/fail2ban/fail2ban.sqlite3 can indicate that retention is broader than the operational requirement. SQLite journaling and write activity can also make memory and disk usage appear high during a large update.
Journal or rotated-log replay
With backend = systemd, Fail2ban reads the systemd journal. A jail pointed at a broad unit set, or a journal containing a large backlog, can process a substantial amount of historical data after startup or reload. The jail manual says rotated journals are ignored by default to avoid too many open files; explicitly enabling rotated-journal processing expands the replay scope and should be deliberate.
Memory that is not in Fail2ban
An nftables set, a long iptables rule list, a firewalld object, conntrack entries, or the journal itself may consume the memory you are attributing to Fail2ban. Confirm the process RSS and inspect the native firewall and kernel state before changing Fail2ban.
Measure the right things before changing configuration
Capture a baseline, then repeat the measurements after several minutes. A single snapshot cannot show whether memory is still growing, has reached a steady state, or is being reclaimed.
| What to measure | Example command or check | What it tells you |
|---|---|---|
| Fail2ban process RSS | ps -C fail2ban-server -o pid,ppid,rss,vsz,etime,cmd |
Resident and virtual memory of the Fail2ban process, separate from kernel and firewall memory. |
| Service state and recent errors | systemctl status fail2banjournalctl -ru fail2ban |
Startup failures, reload loops, backend errors, and the most recent service messages. |
| Overall Fail2ban status | fail2ban-client status |
Enabled jails and whether the daemon responds. |
| Per-jail counts | fail2ban-client status JAILNAME |
Currently failed and banned addresses for a particular jail. |
| Fail2ban log | less /var/log/fail2ban.log or your distribution’s configured log path |
Ban, unban, filter, action, and database errors. The project troubleshooting guide specifically recommends this log for checking errors. |
| Database size | du -h /var/lib/fail2ban/fail2ban.sqlite3 |
Whether persistent Fail2ban state is expanding on disk. |
| Journal storage | journalctl --disk-usage |
Space occupied by systemd journals, not Fail2ban’s resident memory. |
| Firewall state | iptables -L -n -vnft list ruleset |
Rule ordering, counters, chains, and set sizes in the active netfilter implementation. |
Also check free memory and swap, kernel memory, conntrack usage, and the number of entries in any firewall sets. If the Fail2ban RSS is stable but an nftables set or conntrack table is expanding, reducing Python process state will not solve the incident.
Rank #2
Use the logs to identify the trigger
Start with the service journal using the command recommended by the Fail2ban troubleshooting guidance:
journalctl -ru fail2ban
Read from the newest entry backward and look for repeated start/stop cycles, database-lock messages, filter exceptions, action failures, and a jail that is repeatedly loading a large history. Then inspect /var/log/fail2ban.log (or the path configured by your distribution) for a sudden flood of ban and unban events. A repeating sequence can indicate that a backend is replaying old records or that an action is failing and being retried.
Record the timestamp at which RSS began increasing. Compare it with the first attack entries, a service restart, log rotation, journal vacuum, configuration reload, or enabling a new jail. Correlation does not prove causation, but it narrows the state to inspect.
Control ban cardinality and retention
Inspect the effective values in each enabled jail rather than assuming the defaults. Distribution snippets can override the main configuration, and a recidive jail can create a second, much longer-lived ban population.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errors| Setting or feature | Effect on resource usage | Review question |
|---|---|---|
bantime |
How long an address remains banned. Very long or permanent values keep firewall and Fail2ban entries active. | Does the duration match the threat, or is a temporary attack creating indefinite state? |
findtime |
Time window in which failures are counted. | Is the window so broad that old events continue contributing to new decisions? |
maxretry |
Number of matches permitted before a ban. | Would a narrowly tuned threshold reduce accidental and unnecessary bans without missing the attack? |
| Recidive or permanent-ban jail | Aggregates repeat offenders and often uses a much longer bantime. |
Is it duplicating addresses already held by another jail, and is its retention justified? |
| Enabled jail count | Each jail has filters, counters, and potentially its own firewall action. | Are all jails watching services that exist and need protection? |
| Database purge settings | Determine how long historical state remains in SQLite. | Is old failure history retained longer than incident response requires? |
Make one bounded change at a time. For example, shorten an excessive bantime, disable a redundant jail, or reduce a recidive retention period. Keep a copy of the previous configuration and observe both RSS and ban counts after the change. Do not lower maxretry blindly: an overly aggressive threshold can ban legitimate users and increase, rather than decrease, churn.
Clear bans and reset the database safely
There are three different operations, with different consequences: unbanning addresses, restarting the daemon, and deleting persistent state. Choose the smallest operation that addresses the problem.
Remove active bans without deleting history
For a specific jail, list its status first:
fail2ban-client status JAILNAME
Then use the client’s unban operation supported by your installed version. The common form is:
fail2ban-client set JAILNAME unbanip IP_ADDRESS
Repeat for only the addresses that should be released. If you must clear every active ban, use the all-jails operation documented by your package’s fail2ban-client help output, and verify the resulting firewall state immediately. Releasing every address can expose the service again; keep an alternate administrative access path available.
Free tools Windows power users keep installed
One-click scans. No signup required.
Reload configuration with minimal disruption
After editing a jail, prefer a reload when the change is supported by your version:
fail2ban-client reload
Check fail2ban-client status and each affected jail afterward. A reload can still change filters and actions, so confirm that the expected chain or set contains the intended entries.
Understand the restart side effect
Fail2ban’s troubleshooting documentation warns that a restart can unban all addresses and then ban them again as filters process events. That temporary exposure and ban storm can increase traffic, CPU, database writes, and memory. Schedule a restart when you have console or out-of-band access, preserve an emergency allow rule, and watch the logs while the service returns.
Back up before touching SQLite
Stop or quiesce Fail2ban before making a database copy so the backup is consistent:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Rank #4
systemctl stop fail2ban
cp -a /var/lib/fail2ban/fail2ban.sqlite3 /var/lib/fail2ban/fail2ban.sqlite3.backup
systemctl start fail2ban
The exact service name and database path can differ by distribution. Deleting the database is a state reset, not a routine memory fix: it removes persistent history and can cause addresses to be evaluated again. If you intentionally reset it, retain the backup, document the time, and verify that every jail starts cleanly. A smaller database does not guarantee an immediate drop in RSS because Python allocators and firewall objects may retain memory until entries expire or the process is restarted.
Check systemd-journal ingestion
For a systemd backend, inspect each jail’s journalmatch or equivalent service selector. It should target the service that produces the events, not the entire host journal unless that breadth is intentional. A broad selector can make a single jail parse unrelated authentication and application records.
Check whether rotated journals are being included. The manual documents that rotated journals are ignored by default and explains that enabling rotated=on can open many files. If you enabled that option to find older events, disable it after the recovery operation unless continuous historical scanning is genuinely required.
Use the journal tools to manage disk retention:
journalctl --disk-usage
journalctl --vacuum-size=1G
journalctl --vacuum-time=14d
Choose a size or age appropriate for your incident and compliance needs; the values above are examples, not universal recommendations. Vacuuming removes stored journal data and can prevent disk exhaustion, but it does not prove that Fail2ban’s resident memory will immediately fall. After vacuuming, restart or reload only if you have confirmed the backend is still replaying unwanted data.
Recommended Free Tools
Verify that the firewall action is enforcing the ban
A successful Fail2ban log message does not guarantee that packets are blocked. Inspect the native firewall state and counters:
iptables -L -n -v
nft list ruleset
Use the command for the firewall stack actually installed on the host; do not assume that an iptables command reflects an nftables ruleset behind a compatibility layer. Look for the Fail2ban chain or set, its rule order, and packet counters. An allow rule placed ahead of the Fail2ban chain can bypass the ban. A chain or set that grows without bound can consume kernel memory even when the Fail2ban process looks normal.
Best Value
If firewalld manages netfilter, inspect its active zones and the action selected by the jail. If the host uses nftables directly, verify the set name, address family (IPv4 versus IPv6), timeout behavior, and whether the set is attached to the hook that receives the traffic.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Docker traffic often bypasses INPUT
For a service published by Docker, the packet path commonly traverses the FORWARD chain before reaching the container. The Fail2ban troubleshooting guidance states that Docker uses FORWARD to send traffic to containers, so rules in INPUT can have no effect on that traffic.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteInspect the Docker chains and place the enforcement where forwarded traffic can reach it. The project guidance commonly recommends the DOCKER-USER chain for administrator-supplied filtering:
iptables -L DOCKER-USER -n -v
Confirm the actual path for your networking mode, reverse proxy, and published ports. If a proxy terminates the connection on the host, Fail2ban may need to read the proxy’s log and block the client address at the proxy-facing hook. If the application sees only an internal bridge address, correct forwarded-client logging before tuning filters; otherwise you may ban the proxy or host instead of the attacker.
Validate filters and actions before enabling them broadly
Use fail2ban-regex against a representative log sample to confirm that a filter matches the intended failures and does not match routine traffic. Validate IPv4 and IPv6 separately when your action supports both. Then test one jail:
- Back up the current jail configuration and record the baseline RSS, ban count, database size, and firewall set size.
- Run
fail2ban-regexon a small, representative log sample and inspect matched and missed lines. - Reload the single changed jail when supported, rather than restarting every jail.
- Watch
journalctl -ru fail2ban,/var/log/fail2ban.log, process RSS, and firewall counters for at least one normal traffic interval. - Confirm that a test block reaches the intended chain or set and that an allowlisted administrative address remains reachable.
If the jail repeatedly reprocesses the same lines, investigate the backend cursor, journal selector, log rotation behavior, and file permissions before increasing thresholds. If bans appear in Fail2ban but not in the firewall, fix the action or chain placement rather than adding more jails.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Common symptoms and targeted fixes
| Symptom | Likely explanation | Targeted response |
|---|---|---|
| RSS and active bans rise together | Ban cardinality or long retention is the dominant state. | Measure per-jail counts; shorten excessive bantime, remove duplicates, and bound recidive and database retention. |
| RSS rises after every restart, then levels off | Startup is replaying a large journal or log history. | Narrow the backend selector, review rotated-journal handling, and inspect the service journal for replay messages. |
| Fail2ban RSS is stable but host memory falls | Firewall sets, conntrack, journal storage, or another process is consuming resources. | Inspect native rules, set cardinality, kernel memory, conntrack, and journal usage. |
| Logs say “ban” but attacks continue against a container | Traffic is forwarded through Docker and bypasses INPUT, or rule ordering permits it. |
Trace the packet path and inspect DOCKER-USER, FORWARD, published ports, and counters. |
| Database is huge but active bans are modest | Historical failure records or purge settings are retaining old state. | Review database retention, back up the file, and perform a deliberate reset only after confirming the consequence. |
| Memory spikes during a mass unban/reban | A restart or reload caused filters to process a backlog and actions to recreate entries. | Use a controlled reload, narrow replay scope, and schedule disruptive restarts with out-of-band access. |
A prevention checklist for future attacks
- Set a finite, threat-appropriate
bantime; reserve permanent or very long bans for a documented need. - Keep
findtime,maxretry, and recidive settings specific to each service instead of copying one aggressive profile everywhere. - Disable unused jails and avoid multiple jails that record the same event stream.
- Define database purge behavior and monitor
/var/lib/fail2ban/fail2ban.sqlite3size. - For systemd backends, match the intended unit and leave rotated-journal processing off unless you have a reason to scan it.
- Monitor Fail2ban RSS, active bans per jail, database size, firewall set/rule counts, journal disk usage, and conntrack separately.
- Test filters with
fail2ban-regexafter log-format, proxy, container, or distribution changes. - Document the firewall action and packet path, including Docker’s
DOCKER-USERchain where applicable. - Keep console or out-of-band access before a restart, because restart can temporarily unban addresses and then recreate bans.
Bottom line
Do not treat a memory spike as proof of a Fail2ban leak, and do not delete its database as the first response. Establish whether the growth is in the Fail2ban process, retained ban/database state, journal ingestion, firewall objects, or kernel tables. Then make one reversible change—usually bounding ban retention, narrowing a backend, removing duplicate jails, or correcting the enforcement chain—and verify the result with process, database, log, and firewall measurements. The reported 500,000–1,000,000 bans and 2.4 GB process usage show that extreme incidents are possible, but they are not universal limits from which a safe per-ban formula can be calculated.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




