Production readiness

NotifyKit 0.0.x is a preview. The notification model, persistence adapters, preferences, and delivery pipeline are tested, but production reliability depends on infrastructure that the preview does not yet bundle for you.

Do not confuse persistent state with durable dispatch. PostgreSQL preserves NotifyKit records. It does not preserve an in-memory queue job if the process exits before delivery finishes.

Current deployment levels

Use caseRecommended setupCurrent verdict
Demo, local development, testsMemory adapter + fake providerSupported
Prototype with persistent inboxSQLite/Postgres + inline queueSupported; sends add request latency
Non-critical application notificationsPostgres + durable external queue + monitoringPossible with integration work
Security, billing, compliance, or guaranteed deliveryOutbox, durable worker, provider webhooks, suppression, recovery toolingWait for production-stable or own these pieces explicitly
Bulk marketing campaignsAudience management, legal compliance, campaign analyticsUse a purpose-built platform

Queue behavior

QueueBehaviorFailure boundary
inlineQueue()send() waits for deliveryCaller sees failure, but response latency includes provider work
setTimeoutQueue()Runs later in the same processWork can disappear on crash, deploy, or serverless freeze
External durable queueSerializes DeliveryJob for a workerReliability depends on your queue and worker configuration
worker.ts
import { notify } from "./lib/notifykit"

// Your queue worker passes back the persisted DeliveryJob.
await notify.processDeliveryJob(job.data)
Queue redelivery is guarded, but provider delivery is not an exactly-once transaction. NotifyKit skips a job whose delivery record is already terminal. A process can still crash after a provider accepts a message but before the database records success. Use provider idempotency where available and design critical messages for at-least-once delivery.

Checklist before critical delivery

  • Use PostgreSQL and version-controlled migrations reviewed with your app migrations.
  • Write notification intent in the same transaction as the business event, or accept the gap explicitly.
  • Use a durable queue with idempotent job IDs and a separately monitored worker.
  • Ingest provider delivery, bounce, and complaint webhooks.
  • Suppress addresses after hard bounces or complaints.
  • Alert on terminal delivery failures and test the recovery procedure.
  • Load test your actual database, provider, and queue topology.
  • Back up NotifyKit tables and test tenant isolation with your authentication layer.

What the preview does guarantee

The repository continuously tests payload validation, preference resolution, tenant isolation, idempotency, deduplication, retries, fallback behavior, inbox mutations, realtime events, and both SQLite and PostgreSQL adapters. Those guarantees apply to the library code; they cannot replace operational testing of your deployment.