When running SpamAssassin's spamd daemon on Debian systems, memory usage can become a significant concern. The default configuration typically shows these characteristics:
- 32-bit servers: 100-150MB virtual memory (50MB resident) per child process
- 64-bit servers: Approximately double the 32-bit footprint
- Default maximum of 5 child processes during peak loads
Add these settings to /etc/spamassassin/local.cf
:
# Reduce rule memory footprint
bayes_ignore_header X-Mozilla-Status
bayes_ignore_header X-Mozilla-Status2
bayes_ignore_header X-UID
skip_rbl_checks 1
# Disable rarely used plugins
loadplugin Mail::SpamAssassin::Plugin::Rule2XSBody
loadplugin Mail::SpamAssassin::Plugin::AWL
loadplugin Mail::SpamAssassin::Plugin::AutoLearnThreshold
Modify /etc/default/spamassassin
to include:
# Limit child processes
SPAMDOPTIONS="-d --max-children=2 --helper-home-dir"
# Set memory limits
ulimit -v 150000
Create a custom rules file to disable memory-intensive rules:
# In /etc/spamassassin/custom.cf
ifplugin Mail::SpamAssassin::Plugin::Rule2XSBody
body MY_LOWMEM_RULE /.../ __HIT__ __MISS__
score MY_LOWMEM_RULE 0.1
endif
After making changes, recompile rules for better performance:
sa-compile --install
systemctl restart spamassassin
Verify memory usage improvements with:
ps -eo pid,user,args,%mem,rss --sort=-rss | grep spamd
Consider setting up a cron job to log memory usage periodically for trend analysis.
When running SpamAssassin on Debian systems, many administrators notice each spamd
child process consumes 100-150MB on 32-bit systems and nearly double that on 64-bit architectures. With default configurations (Pyzor/AWL/Bayes disabled, sa-compile enabled) and peak loads triggering multiple child processes, memory usage can balloon to 600MB.
First, let's examine critical local.cf
adjustments:
# Reduce rule memory footprint score ANY_BOUNCE_MESSAGE 0 score HTML_MESSAGE 0 score HTML_FONT_LOW_CONTRAST 0 # Disable heavy plugins loadplugin Mail::SpamAssassin::Plugin::TextCat 0 loadplugin Mail::SpamAssassin::Plugin::ASN 0
Modify /etc/default/spamassassin
:
OPTIONS="--max-children=2 --min-children=1 --child-helper-threads=2 \ --nouser-config --min-spare=1 --max-spare=1" MAX_CHILDREN=2
This forces tighter process control while maintaining reasonable throughput.
Rebuild rules with aggressive optimizations:
sa-compile --keep-tmprules --optimize-cf --no-network
Then add to local.cf
:
use_bayes 0 bayes_auto_learn 0 use_pyzor 0 use_auto_whitelist 0
For bare metal servers, consider these sysctl tweaks:
vm.swappiness = 1 vm.vfs_cache_pressure = 50 vm.dirty_ratio = 10 vm.dirty_background_ratio = 5
Implement this pre-filter in your MTA (Postfix example):
smtpd_mime_restrictions = check_mime_access regexp:/etc/postfix/mime_size_limits # /etc/postfix/mime_size_limits /^Content-Length:.*[5-9][0-9][0-9][0-9][0-9][0-9]/ REJECT
To identify exactly which rules consume memory:
spamassassin --debug --lint 2>&1 | grep 'memory' | sort -k5 -n
For Docker deployments, enforce memory limits:
docker run -d --memory=256m --memory-swap=512m \ --name spamd spamassassin