Skip to main content

Environment variables

Without API_KEY / APP_ID the client degrades to log-only (does not throw) and the health probe reports the component as down.

Idempotency, retries and observability

  • Idempotency: the consumer uses queue_event_id as queue_event.source_event_id; a duplicate redelivery is a no-op.
  • Retries: exponential backoff on transient (5xx / network) errors. NonRetryableNotificationError becomes a logged skip with no retry.
  • Event types: segmented by channel (vercel_queue.notification.push|in_app|sms|live_activity, …unified fallback).
  • Success context: handlers return context.oneSignalId for correlation.

Runbook — DLQ and replay

Failures that exhaust retries land in the shared DLQ infrastructure (queue_dead_letter + queue_replay_job).
1

Detect

Query queue_dead_letter filtering by event_type LIKE 'vercel_queue.notification.%'.
2

Diagnose

Review queue_event_attempt (last error) and handler logs by correlation / queue_event_id.
3

Fix the root cause

OneSignal credentials, phone number or payload.
4

Reprocess

Enqueue a queue_replay_job for the affected queue_event rows.
5

Verify

The row moves to processed with context.oneSignalId.
Forcing an invalid API key in dev is the fastest way to observe the retry → DLQ → replay cycle end-to-end.

Health

A cheap active probe (GET /apps/{app_id}, without consuming quota) combined with real traffic paints the INTEGRATION_ONESIGNAL heartbeat on the status page.

Mobile integration checklist

1

Initialize the SDK

Use the environment’s OneSignal App ID.
2

Bind the user

On authentication call OneSignal.login(auth.users.id) to set the external_id.
3

Render in-app

Handle the data-only push of the in_app channel.
4

Register phone

Persist the user’s E.164 phone for SMS.
5

Respect preferences

Read GET /v3/notification/preference/me and persist changes with PUT/PATCH .../me.