Skip to content

Performance Tuning

Most deployments work well with the defaults. Tune these settings when startup reconciliation handles large CAPI lists, a slow router times out, or you need predictable restart windows.

mikrotik.pool_size controls how many RouterOS API sessions the bouncer can use for parallel work such as reconciliation removals.

mikrotik:
pool_size: 4

Guidance:

Router classSuggested value
Small home router1-2
Mid-range RouterOS 74
Large CAPI deployments6-8

The configured value must be between 1 and 20. On startup, the bouncer queries RouterOS API max-sessions and caps the effective pool to max-sessions - 2, ensuring at least two sessions remain available for other RouterOS operations.

Check or raise the RouterOS limit:

/ip/service/print where name=api
/ip/service/set api max-sessions=1000

During reconciliation, additions use temporary RouterOS scripts instead of one API call per IP. Each script carries up to 100 addresses.

That chunk size is not about message size — the RouterOS API takes words far larger than these scripts, and a chunk of 1,000 entries transfers without complaint. It is the trade between amortizing the four round trips each chunk costs (find, add, run, remove) and how long a single non-interruptible script run holds the router.

Sweeping it against an RB5009 — five interleaved rounds of 4,000 entries at 50/100/250/500/1000 — the medians land between 4.36 s and 5.78 s across that whole 20× range. The useful result is that the sweep cannot resolve a winner: within one chunk size the interquartile range reaches 2.55 s, larger than the 1.43 s that separates the best size from the worst, and which size looks best depends on which estimator you use (median and minimum pick 1,000; the mean picks 100).

What is stable is the shape: inserting a row costs ~1.2–1.3 ms and dominates everything else, so a 22,000-entry import spends roughly 27 s inserting against somewhere between 0.2 s and 2.3 s of chunk scaffolding. There is no reason to change this value, and no measurement here that would tell you what to change it to.

If a bulk script fails, the bouncer logs a warning and falls back to individual adds for that chunk. Duplicate entries are skipped or refreshed without reconnecting the API session.

Increase mikrotik.command_timeout if RouterOS is slow during large list operations:

mikrotik:
command_timeout: "60s"

Increase mikrotik.connection_timeout only when the initial TCP/API login itself is slow:

mikrotik:
connection_timeout: "20s"

Startup reconciliation always runs. Periodic reconciliation repairs drift after startup.

crowdsec:
reconciliation_interval: "15m"

Use 0 to disable periodic reconciliation, or a value of 1m or greater to enable it. Values between 0 and 1m are rejected at startup.

Short intervals repair drift faster but read the whole RouterOS address list more often. What that costs is measurable: on an RB5009 holding 22,332 entries a no-drift pass takes 1.86 s, of which the two list reads are 98.5%. At the default 15m that is a 0.2% duty cycle; at 1m it is 3.1%.

The cost scales with how many entries the router holds, not with how much drift there is to repair — a pass that finds nothing costs very nearly what a pass that fixes something costs. So the interval is worth lengthening on a large list and a modest router, and there is little to gain from shortening it below what your tolerance for undetected drift actually requires.

metrics.track_processed creates passthrough counting rules so the bouncer can report total evaluated traffic, not only dropped traffic.

metrics:
track_processed: true

Set it to false to avoid those extra counting rules:

metrics:
track_processed: false
crowdsec:
origins: ["crowdsec", "cscli"]
reconciliation_interval: "30m"
mikrotik:
command_timeout: "60s"
pool_size: 6
metrics:
enabled: true
routeros_poll_interval: "30s"
track_processed: true

For small routers, prefer local-only mode, pool_size: 1 or 2, and avoid full CAPI until you have measured reconciliation time.