Persistence

By default, Notiway delivers notifications only to clients that are connected at the time of delivery. If a client is offline, the notification is lost.

Persistence changes this. When a notification is persisted, Notiway stores it and replays it to clients that were offline or had not yet joined the target audience.


Enabling Persistence

Persistence is controlled per notification via the metadata object. It is off by default — the producer must explicitly opt in.

{
  "id": "order-service-order-placed-2025-01-01T10:00:00Z",
  "type": "order-placed",
  "body": { "orderId": "ord-123" },
  "routing": { "audienceType": 2, "audienceValue": "acme-corp" },
  "metadata": {
    "producer": "order-service",
    "isPersisted": true,
    "persistedTTL": "2025-01-01T10:30:00Z"
  }
}
FieldTypeDefaultDescription
isPersistedbooleanfalseSet to true to persist the notification.
persistedTTLdatetime (UTC)+30 minutesAbsolute expiry time. After this, the notification is no longer replayed.

If persistedTTL is omitted, Notiway defaults to 30 minutes from the time the notification is published. There is no maximum TTL — you can set it to days or weeks depending on your needs.

Testing mode: Persistence is not supported when using the HTTP test endpoint (Config__Testing=true). Notifications sent via /test/notifications are delivered in-memory only and are never stored, regardless of the isPersisted flag.


When Persisted Notifications Are Delivered

A persisted notification is replayed in three situations:

  flowchart LR
    GW["Notiway Gateway"]@{ icon: "mdi:server", form: "square" }

    subgraph T1[" "]
        direction TB
        T1H["🔌 Client connects"]
        T1B["<b>Global</b> audience replayed<br/><b>User</b> audience replayed"]
        T1H --> T1B
    end

    subgraph T2[" "]
        direction TB
        T2H["👥 Client joins a Tenant or Group"]
        T2B["<b>That audience</b> replayed"]
        T2H --> T2B
    end

    subgraph T3[" "]
        direction TB
        T3H["⚡ Client is already connected"]
        T3B["Delivered <b>immediately</b><br/>no replay needed"]
        T3H --> T3B
    end

    GW --> T1
    GW --> T2
    GW --> T3

    style GW font-size:14px
    style T1H font-size:15px,font-weight:bold
    style T2H font-size:15px,font-weight:bold
    style T3H font-size:15px,font-weight:bold
    style T1B font-size:13px
    style T2B font-size:13px
    style T3B font-size:13px

Expired notifications (past their persistedTTL) are never replayed.

Order matters: Register your notification type handlers before joining an audience. Persisted notifications are replayed at the moment of joining — handlers that are not yet registered will miss them. See Routing for details.


Read and Deleted State

Each persisted notification carries two state flags that your client can act on:

  • isRead — indicates the user has already read this notification. What you do with this is up to you — show a dot, grey it out, hide it entirely.
  • isDeleted — indicates the user has deleted this notification. Deleted notifications are never delivered or replayed to that user again.

When the client notifies the gateway that a notification was read or deleted, Notiway propagates that change to all other connected clients for that user. All devices stay in sync automatically.

See Connection Management for the hub methods used to trigger these state changes.


Storage

Persisted notifications are stored via the configured Storage plugin. See Storage Plugins for available options and configuration.