gem
Notifications
How notifiers behave
Every notifier runs after the backup finishes, on success and on failure alike. None of them can fail a run: a broken webhook or an unreachable host is written to stderr and the exit code still reflects the backup itself. A notification problem must never look like a backup problem.
Stdout is registered by default. Sentinel and Slack are opt-in.
Sentinel
Setting the key is the entire integration.
config.sentinel_key = ENV["BB_SENTINEL_KEY"] After every run the gem POSTs a report to https://boringbackup.com/ping/<key>. That arrival is what
keeps the monitor alive, and the body is what fills in the size, duration and per-store detail
you see on the activity page.
Delivery is retried up to 3 times, with a one second then two second pause, for server errors and rate limits. Connect and read timeouts are 5 and 10 seconds. After that it gives up and warns.
The payload
{
"version": 1,
"status": "success",
"error": null,
"database": "db_production",
"engine": {
"name": "postgresql",
"client": "17.2",
"server": "17.2"
},
"bytes": 2214592512,
"duration": 48.302,
"stores": [
{
"store": "s3",
"success": true,
"key": "database/db_production/2026/07/29-03-00-04-812.dump",
"bytes": 2214592512,
"duration": 48.302,
"error": null
}
]
} | field | meaning |
|---|---|
| status | success, partial_success or error. Only an explicit non-success marks the run
failed |
| engine | the dump tool's version and the server's, as each reported it. Sentinel decides what counts as a mismatch, so the rule can change without a new gem release |
| bytes | largest byte count across stores, which is the size of the dump |
| duration | seconds taken by the slowest store |
| stores | one entry per destination, each with its own key, size, time and error |
Sentinel stores the body verbatim and parses it defensively, so an older gem that omits a field still records a healthy ping. When a version cannot be read, the gem sends what it has and sentinel shows nothing rather than a warning, because a check that did not happen should not look like a problem. See version mismatch for how the comparison is made, and the ping API for the endpoint itself.
Pointing somewhere else
config.sentinel_host = "https://sentinel.internal" Useful for a staging monitor or a self-hosted instance. A host without a scheme gets https, except for localhost and loopback addresses, which get http so local development works.
Slack
config.notifier(:slack) do |slack|
slack.webhook_url = ENV["BACKUP_SLACK_WEBHOOK"]
end Posts the result of every run to an incoming webhook, success included. This is the gem talking about what it just did.
Sentinel's Slack integration answers a different question: it alerts when a backup that should have run did not report at all. A gem that never starts cannot tell you it never started, which is the whole reason the monitor lives somewhere else. Running both is reasonable, and if you only want one, take the sentinel one.
Stdout
Registered by default, so a backup invoked from your own code or a job prints its result to the
log. bb backup removes it before running, since the command already
prints a nicer version of the same thing.
Turning reporting off
config.report = false Silences every notifier, sentinel included. Worth setting in the test environment so a suite that exercises the backup path does not ping a live monitor.