Originally published on Cronpimo: Beyond a completion signal: three useful backup metrics.

The overnight backup finishes without an error and its completion signal arrives. Yet the new archive contains only a fraction of the expected data. Perhaps a source directory was not mounted; perhaps someone intentionally narrowed the selection. A green completion signal cannot distinguish those cases. Three additional measurements can help you decide what to investigate.

The example below is a fictional daily full export into a compressed archive. Its numbers illustrate the checks. They are neither recommended defaults for arbitrary backups nor results from a customer incident.

Define what each measurement means

Use the same definitions for every run: files counts backed-up source files in the current manifest, bytes measures the completed compressed archive, and duration_seconds covers the backup from its start to confirmed completion at the destination. The HTTP request that delivers the completion signal is not part of that duration.

Our example job has these deliberately chosen limits:

Metric Reported value Allowed range
Files 120 At least 100
Archive size 50 MiB 40 to 100 MiB
Duration 180 seconds 60 to 600 seconds

1. Count: did the expected selection get backed up?

A file count helps reveal a suddenly smaller selection. If this export reports 3 files instead of 120, inspect source paths, mounted volumes and exclusion rules. Successfully creating an archive does not mean the intended selection went into it.

Do not simply count files in the destination directory: one archive remains one file regardless of how many source files it contains. Use the result or manifest from this particular backup run. A database backup might need a different meaningful count; its internal backup files may say little about completeness.

Nor does 120 matching 120 prove identical contents. The limit detects certain differences, not every form of damage. Choose it using known, checked runs and the data structure you actually expect.

2. Volume: was unusually little or much written?

A 2 MiB archive falls below the example's lower limit. That calls for investigation, but does not establish a cause. Check whether less content was backed up or whether its compressibility changed. Switching compression methods can also alter the comparison.

An upper limit can reveal unexpectedly large backups: newly included logs, for example, or old archives accidentally added to the selection. Assess full and incremental backups separately. A small amount of new data can be perfectly valid for an incremental run.

The example reports bytes: 50 MiB is 52,428,800 bytes, with limits of 41,943,040 and 104,857,600 bytes. Keep the unit consistent when collecting, sending and configuring the measurement.

3. Duration: was the process unusually short or long?

A much shorter run may fit the missing-selection hypothesis. A longer one may reflect more data, slower storage or a stalled transfer. None of these measurements identifies a cause automatically. Compare duration with the count and volume from the same run.

A lower duration limit is useful only when a faster run would genuinely be suspicious. An optimization or storage change may require revising it. Here, the upper limit of 600 seconds means a completed run reporting 601 seconds violates the metric rule.

A duration reported after completion cannot detect a process that never finishes. Monitor missing or late signals as well. The cron job monitoring guide distinguishes starting a process, completing it and checking its result.

Send measurements with the completion signal

The heartbeat guide covers setup. For a completion-only signal, the illustrative payload is:

{ "kind": "success", "event_id": "backup-example-001-end", "metrics": { "files": 120, "bytes": 52428800, "duration_seconds": 180 } } 

Replace those numbers with measurements from the run that just finished, and use a unique event identifier for each signal. If you also send a start signal, both start and completion need the same run_key, unique to that run.

Cronpimo's minimum and maximum limits are inclusive: 100 files, 40 MiB, and either 60 or 600 seconds are inside these rules. Each configured metric must be present in a success signal. If duration_seconds is missing, the heartbeat is classified as failed despite kind: success. An unavailable measurement is not the same as zero seconds. Send numbers as JSON numbers; do not replace missing measurements with invented values.

Turn an unusual result into a specific check

First inspect the affected run and its measurement source. Are the manifest and archive really from today? Was the selection changed? Adjust limits after explaining the difference. Cronpimo does not learn these limits automatically from earlier backups. If your workflow instead exposes a readable status endpoint, the result-checking guide shows how to evaluate the result and its freshness separately.

Continue to schedule restoration tests. Even specialized integrity checkers do not replace them; the PostgreSQL documentation for pg_verifybackup makes that distinction explicitly. A complete set of plausible measurements is a useful operational signal. Restoring the required data is a separate test.

Disclosure: This article and its cover illustration were created autonomously with AI for Cronpimo. Its technical claims were checked against the current implementation and the referenced documentation. The heartbeat examples and metric boundaries were validated with isolated tests against the current code.