For AI agents: the complete documentation index is available at https://payhon.github.io/AppKernia/en-US/llms.txt, the full documentation bundle is available at https://payhon.github.io/AppKernia/en-US/llms-full.txt, and this page is available as Markdown at https://payhon.github.io/AppKernia/en-US/concepts/notification-architecture.md.

Notification and push architecture

AppKernia does not send to every device inside an HTTP request. The server uses PostgreSQL + River for asynchronous jobs and commits the notification, run record, and queued job in the same database transaction.

The pipeline serves Admin publishing, trusted service submissions, and Mobile in-app notifications. In-app delivery is the baseline: it remains available when a user disables push, a device has no supported provider, or a provider delivery fails.

End-to-end data flow

The synchronous request performs trusted validation and commits a transaction. Workers publish, fan out to devices, and call providers asynchronously. Business facts and jobs share PostgreSQL to avoid partial dual writes.

Three notification jobs

Task kindPurposeMax attemptsWorker timeout
appkernia-message-publishPublish scheduled messages and deliver in-app recipients530 seconds
appkernia-push-fanoutEvaluate subscriptions and create per-device deliveries590 seconds
appkernia-notification-deliveryDecrypt one device token and call its provider590 seconds

All three use the notifications queue. Business modules depend on platform/jobqueue, not on the River Client. Task kind, queue, maximum attempts, timeout, and automatically retryable classes are registered at compile time.

Sources of truth

DataPurposeRetention
river_jobRiver's live scheduling stateRiver runtime policy
notify.messages / notify.recipientsNotification snapshot, frozen audience, and in-app delivery factNotification policy
notify.deliveriesPer-device acceptance, failure, invalid token, and open eventsNotification policy
notify.message_runsPipeline state from scheduling through delivery completion90-day detail
jobs.task_runs / jobs.task_attemptsTenant/App-scoped job index, attempt result, and Trace ID90-day detail
notify.delivery_daily_metricsDaily metrics by app, environment, channel, provider, and result13 months

Task projections never store River Args, full stacks, tokens, payloads, secrets, or raw provider responses. Use the Trace ID from a safe summary to investigate the full trace in the deployment's observability stack.

Delivery result semantics

Normalized resultBehavior
acceptedMark provider acceptance; this does not promise that the device displayed the notification
invalid_tokenStop the delivery and immediately invalidate the device binding
throttledHonor Retry-After, exponential backoff, and jitter
transientRetry a clearly transient failure automatically
permanentDo not retry automatically
auth_config_errorFault the channel; fix and preflight it before a manual retry
unknown_after_writeDo not replay automatically; the provider may have accepted it, so only a risk-confirmed retry is allowed

Workers safely no-op when a notification has been cancelled or expired, or when a duplicate job arrives. An operator retry creates a new task linked to the original instead of rewriting River history.

Security boundaries

  • A global kill switch, app/environment channel state, user subscription, and OS permission all gate push delivery.
  • Tokens are encrypted and deduplicated with an HMAC hash. Credentials are write-only and encrypted; Admin APIs never return plaintext.
  • A notification-open payload permits only a schema version, delivery/message IDs, a controlled route_key, an opaque resource ID, and bounded route parameters.
  • Arbitrary URLs, component names, dynamic scripts, silent wake-up, and arbitrary background execution are unsupported.
  • Prometheus labels use low-cardinality dimensions such as App, Provider, Category, and Result—never user IDs or tokens.

Acceptance boundary

A mock provider, source compilation, or provider acceptance does not prove a real device displayed a notification. Before production enablement, validate each provider's account entitlement, credentials, package or bundle identity, signing fingerprint, privacy/network behavior, and foreground, background, terminated, offline-recovery, and notification-open behavior on physical devices.

Continue with Push channel configuration, Notification operations, Notification API, and the Mobile permission center.