Skip to main content

Migrating from SpamAssassin to Rspamd

This guide walks you through replacing SpamAssassin (SA) with Rspamd. It covers the key architectural differences, a step-by-step migration path, and practical advice for a safe rollout.

Overview

SpamAssassinRspamd
LanguagePerlC core + Lua plugins
I/O modelSynchronous, per-message fork/threadAsynchronous event loop, multi-worker
ConfigurationPerl-style .cf filesUCL (HCL-like) + Lua
Statistics backendBerkeley DB / SQL / RedisRedis (recommended)
Verdict modelNumeric score; MTA decidesScore + action (no action, greylist, add header, rewrite subject, reject) returned to MTA
Web UINone (third-party tools)Built-in controller worker

Rspamd ships with native equivalents for most SA functionality -- DKIM, DMARC, SPF, Bayes, fuzzy hashes, URL blocklists, and more -- enabled by default. In most cases you do not need to port SA rules; Rspamd's built-in modules provide equal or better detection quality with significantly lower resource usage.

Migration checklist

  1. Install Rspamd from official packages.
  2. Integrate with your MTA.
  3. Set up Redis for statistics and other modules.
  4. Review action thresholds to match your policy.
  5. Migrate custom SA rules if needed (most users can skip this).
  6. Train Bayes statistics from your mail corpora.
  7. Run in shadow mode alongside SA, then cut over.

MTA integration

See the full MTA integration guide. The recommended patterns are:

MTAMethod
Postfix / SendmailMilter protocol via Rspamd proxy worker (default on port 11332)
EximHTTP integration via spamd_address with variant=rspamd
Any HTTP-capable MTAPOST to /checkv2 on the normal worker (default on port 11333)

If you currently use SA via spamc/spamd, the closest equivalent is rspamc talking to the normal or controller worker over HTTP.

Redis

Rspamd relies on Redis for Bayes statistics, greylisting state, rate limits, reply tracking, and several other modules. Ensure a Redis instance is reachable and configure it in local.d/redis.conf:

# local.d/redis.conf
servers = "127.0.0.1";

For full details see Redis configuration.

Actions and thresholds

SA produces a numeric score and leaves the delivery decision to the MTA or a wrapper script. Rspamd returns both a score and an action. The default action thresholds are:

# Default actions (configured in local.d/actions.conf or via metrics)
actions {
reject = 15;
add_header = 6;
greylist = 4;
}

If your SA setup marks messages as spam above score 5.0 (the common SA default), consider setting add_header to a similar value. You can also define rewrite subject if your users rely on subject-line markers:

actions {
reject = 15;
rewrite_subject = 7;
add_header = 5;
greylist = 4;
}

See Actions and scores for the full reference.

Mapping SA features to Rspamd

The table below maps common SA plugins and features to their Rspamd equivalents:

SpamAssassinRspamd equivalent
Bayes classifierBuilt-in Bayes classifier (Redis backend)
Network tests (DNS blocklists)RBL module (enabled by default)
URIBL / SURBLRBL module with URL-specific lists
DKIM verificationDKIM module
DKIM signingDKIM signing module
SPF checksSPF module
DMARCDMARC module
RazorExternal services module (Razor integration)
PyzorExternal services module (Pyzor integration)
DCCDCC module or External services
Fuzzy hashesFuzzy check module (Rspamd native fuzzy storage)
AWL (auto-whitelist)Reputation module
TextCat (language)Built-in language detection
body / rawbody / header rulesRegexp module or SpamAssassin module for direct import
Meta rulesComposites
rewrite_header Subjectrewrite subject action with subject pattern in actions
Per-user preferencesSettings module
SA shortcircuitForce actions module or want_spam in settings

Migrating SpamAssassin rules

Most SA checks have native Rspamd equivalents that are faster and better maintained. Migrate only custom rules that you have written yourself and that have no Rspamd equivalent. Importing the entire SA ruleset is unnecessary and will degrade performance.

If you do need to import SA rules, use the SpamAssassin module:

# local.d/spamassassin.conf
spamassassin {
# Your custom rules only
ruleset = "/etc/rspamd/sa-rules/local.cf";
# Optionally include upstream SA rules as a baseline
base_ruleset = "/var/db/spamassassin/3.004002/updates_spamassassin_org/*.cf";
# Limit regex match window for performance
match_limit = 100k;
}

Supported SA features inside the module include: body, rawbody, meta, header, uri rules, some eval functions, and a subset of plugins (HeaderEval, MIMEEval, BodyEval, FreeMail, ReplaceTags, RelayEval, MIMEHeader). Network plugins and HTML-specific plugins are not supported -- use Rspamd's native modules instead. See the module documentation for full details.

tip

Set alpha = 0.1 in the spamassassin config to promote all SA rules with a score above 0.1 to full Rspamd symbols. This makes them visible in the web UI and logs, which helps during the migration period.

Statistics and training

Rspamd uses the OSB (Orthogonal Sparse Bigram) tokenizer with Redis storage. SA Bayes databases cannot be imported -- you must retrain from scratch.

Initial training

Feed your existing ham and spam corpora to Rspamd using rspamc:

rspamc learn_ham /path/to/ham/maildir/
rspamc learn_spam /path/to/spam/maildir/

Both commands accept individual files, directories (recursed), and mbox files. Rspamd requires a minimum number of learns for both classes before Bayes produces results (default: 200, controlled by min_learns). See Statistics settings for all options.

Autolearn

Rspamd can learn automatically from messages that score clearly above or below configurable thresholds. Enable autolearn in local.d/classifier-bayes.conf:

autolearn {
spam_threshold = 6.0;
ham_threshold = -0.5;
check_balance = true;
min_balance = 0.9;
}

This is equivalent to SA's bayes_auto_learn but with finer-grained controls. See the autolearn reference for all options.

User feedback via IMAP

For ongoing training from user actions (moving messages to/from Junk), configure IMAPSieve with Dovecot to call rspamc learn_spam or rspamc learn_ham when users reclassify messages.

Statistics expiry

Unlike SA, Rspamd can automatically expire old statistical tokens to keep the database fresh. Enable the bayes_expiry module to prevent unbounded growth.

Rollout strategy

A safe migration follows these stages:

1. Shadow mode

Run Rspamd alongside SA without affecting mail delivery. Use the proxy worker's mirroring feature to send a copy of traffic to Rspamd while SA remains the production filter:

# local.d/worker-proxy.inc
upstream "production" {
default = yes;
self_scan = yes;
}

Compare Rspamd headers (X-Spamd-Result) with SA headers to identify threshold differences.

2. Tune thresholds

Adjust action scores in local.d/actions.conf until false positive and false negative rates match or improve on your SA setup. Pay special attention to:

  • add_header threshold vs. your SA required_score
  • reject threshold (SA typically does not reject; set this conservatively)
  • Greylisting threshold if you did not use greylisting with SA

3. Cut over

Switch your MTA content filter from SA to Rspamd. Keep SA installed but disabled for a rollback window.

4. Monitor

Use the built-in web UI (controller worker, default port 11334) to monitor symbol hits, action rates, and Bayes accuracy. Check BAYES_SPAM and BAYES_HAM hit rates to verify that autolearn is keeping the corpus balanced.

Common pitfalls

ProblemSolution
Attempting to import SA Bayes databaseNot supported. Retrain using rspamc learn_ham/learn_spam from corpora.
Importing the entire SA rulesetUnnecessary and slow. Migrate only your custom rules; disable or remove upstream SA rules.
Redis not running or unreachableStatistics, greylisting, ratelimiting, and replies all require Redis. Verify connectivity before starting Rspamd.
Score mismatch after migrationSA and Rspamd use different scoring scales. Do not copy SA scores verbatim; tune Rspamd action thresholds independently.
Missing X-Spam headers for downstream filtersConfigure milter_headers module to add X-Spamd-Result, X-Spam-Status, or custom headers.
Per-user Bayes with multiple recipientsEnable per_user in the classifier config and use LDA-mode delivery so each message is attributed to the correct user. See Statistics settings.

See also