This episode teaches Bacula performance tuning (concurrent jobs, spool size, device polling, benchmarks) and production monitoring via bconsole status, Nagios/Zabbix plugins, and automatic alerts when a job fails, complete with a simple notification script example.

A backup system that "runs" is a different thing from a backup system that is "watched". The one that runs produces successful jobs; the one that is watched also tells you when it doesn't. In episode 20 we bring two abilities together: making backups run faster with tuning, and making every failure visible — not waiting to be discovered.
Start with measurement-based performance tuning, then monitoring with bconsole, Nagios/Zabbix plugins, and job-failure alerts.
Bacula can run several jobs at the same time. The Maximum Concurrent Jobs parameter exists in several resources:
Director {
Name = bacula-dir
Maximum Concurrent Jobs = 20
}Device {
Name = FileStorage
Maximum Concurrent Jobs = 4
...
}The more concurrent jobs, the heavier the load on CPU, disk, and the catalog. The rule of thumb: measure first, increase gradually. Start with 2-4 jobs per device, then raise while monitoring.
Spooling makes the Storage Daemon write data to a spool file (fast disk) before moving it to the final media. This minimizes gaps on sequential media (tape) and avoids tape "shoe-shining" (moving back and forth). Configured in bacula-sd.conf:
Storage {
Name = bacula-sd
Spool Directory = /var/lib/bacula/spool
Maximum Spool Size = 5 GB
Maximum Job Spool Size = 1 GB
}A spool too small doesn't help; one too large can fill up at an unexpected moment. Spool size = average size of one job × tolerance.
The Storage Daemon checks media periodically (Device Polling Interval). For a tape waiting on an operator, polling determines how quickly Bacula notices the tape is loaded:
Device {
Name = TapeDrive
Device Polling Interval = 15 min
...
}An interval too frequent burdens the SD; too rare slows down detection of new media.
Warning
Bacula performance is most often bottlenecked by one device limited to Maximum Concurrent Jobs = 1 while jobs pile up in the queue. Check status dir — if many jobs are waiting for the same storage, that's not a catalog tuning problem, it's device capacity.
All tuning must be data-driven. Build a simple benchmark:
* run job="Backup Web" level=Full yes
* list jobs | grep "Backup Web"Record the Bytes and Job Elapsed Time columns. Divide bytes by time to get per-job throughput. Compare after every configuration change — this is your tuning compass.
The first monitoring is always bconsole:
* status dir
* status sd
* status allAlso get into the habit of checking failed jobs:
* list jobs | grep -E "Error|Canceled" | tail -10Before depending on big tools, build a non-interactive notification script — bconsole supports one-shot commands:
#!/bin/bash
FAILED=$(bconsole -c /etc/bacula/bconsole.conf -c 'list jobs' \
| grep -cE "Error|Canceled")
if [ "$FAILED" -gt 0 ]; then
echo "Bacula job problem" | mail -s "[BACULA] Job failed" oncall@example.com
fiRun it via cron every 15 minutes. This is the minimum safety net that has saved many admins before full monitoring is in place.
For full integration, use plugins that consume bconsole output:
bconsole -c 'list jobs' and returns OK/CRITICAL based on status. The check_bacula script is available in community repositories.system.run executing non-interactive bconsole commands, or use a trapper receiving job results from a script on the Bacula server./usr/lib/nagios/plugins/check_bacula -w 1 -c 3
# OK: last job succeeded 5 minutes ago
# CRITICAL: no successful job in 3 daysBuild alert criteria based on the age of the last successful job per client — not just the last job's status, because a system running nothing also "hasn't failed".
The most direct alert source is the Messages resource on each daemon. Mail failures specifically:
Messages {
Name = Standard
mail = oncall@example.com = JobErrors, FatalErrors
}With JobErrors, FatalErrors, email is only sent when a job genuinely has problems — not a spam per success. For team environments, add chat/ops tool integration (webhooks) through a script called by mailcommand.
Note
Alerts must contain context: job name, client, and age of the failure. An alert saying only "Job Error" will be ignored by the on-call team within a week. Make sure your script/mailcommand includes the JobId and job name.
Monitoring isn't one tool — it's a daily ritual:
list jobs | grep Error — check the night.status sd for stuck devices.* list jobs | tail -30Key takeaways:
In the next episode, episode 21, we'll explore the Bacula roadmap and community — Enterprise evolution (plugins, dedup), Community maintenance, the Bacula conference, and resources such as bacula.org, the bacula-users mailing list, and the GitHub bacula/bacula. This is how you keep following the direction of a project that has been running for 25 years.