Skip to content

Records, test send and metrics

Answer 'did my push go out, and why not' from a send's record, try a push on one user, and watch the counters.

The record of a send

Every send leaves one record, kept for push.send_retention (30 days by default). It holds counts, never content: no title, body, data or token, and no user ids (those live only in the send’s jobs, which follow the realm’s job retention).

FieldMeaning
id, kind, sender, created_atThe send, its template kind (raw for a message the function wrote), who sent it (function:<database>/<name> or admin:<actor>) and when
usersHow many users were named; null for an audience
queued, limited, no_devices, no_consentUsers handed to delivery, users over their limit, users with no device to reach (a silent push skips browsers), users who don’t hold the consent the send requires
sent, invalid, failedDevices the provider accepted, devices removed as dead, devices not delivered to
planned, batches, batches_done, units, units_doneHow far the work is
completed, completed_atEverything is done
backd push sends --realm acme                          # the latest, newest first
backd push sends --realm acme --kind order-shipped
backd push sends --realm acme --function main/notify --limit 10
backd push sends --realm acme --id ps_d3c9ljp8hc2g00b6s1m0

The admin interface shows the same on its Push page (Admin interface). The admin API: GET /_admin/push (the configuration state and the secrets still missing), GET /_admin/push/sends (filters kind, function, since, until, limit, skip) and GET /_admin/push/sends/{id}. Both need the functions area, and read-only administrators may use them.

Why a push didn’t arrive

What the record saysWhat it means
limited > 0The user was over push.limits.per_user. Nobody is exempt, test sends included
no_devices > 0The user has no device whose session is alive (or only browsers, for a silent push)
no_consent > 0The send has requires_consent and these users never gave that consent, or withdrew it
invalid > 0The provider said the token is dead; the device was removed and the app registers again at its next launch
failed > 0The provider refused it for good, or the unit ran out of attempts. The worker’s log says why, without tokens
not completedBatches or units are still running, or waiting out a retry backoff

The test send

backd push test --realm acme --email ana@example.com --title "Test" --body "Does it ring?"
backd push test --realm acme --email ana@example.com --kind order-shipped --data '{"order_no": "A-17"}'

POST /_admin/push/test sends to one user, rendered and checked like any push. It needs the users area, is audited as push.test, and counts toward the user’s limits: there is no administrator bypass. The answer says how many were queued, limited or had no_devices; follow the delivery with backd push sends --id.

Metrics

On the metrics endpoint, labeled by realm:

MetricLabelsCounts
backd_push_users_totaloutcome: queued, limited, no_devices, no_consentUsers, as batches are planned
backd_push_deliveries_totalstatus: sent, invalid, failedDevices, as units are delivered
backd_push_devices_pruned_totalreason: invalid, stale, session, cap, movedDevices removed from the registry

A worker that dies mid-send is counted again when its batch runs again, so these are for rates and alerts, not accounting: the records are exact.

Edit this page · Last updated 15 Oct 2026