Skip to main content
Run Pulse as a live, reconnectable feed. Keep the receive path fast, preserve close codes, and reconcile externally when your application requires complete or confirmed transaction state.

Production checklist

  • Copy the target and token from the same dashboard location.
  • Permit outbound UDP to the displayed Pulse port.
  • Keep certificate and hostname validation enabled.
  • Use an explicit account or program filter unless you know the selected access includes an unfiltered feed.
  • Move parsing results into a bounded application queue instead of doing slow work in the receive loop.
  • Record the feed, target location, reconnect count, close code, processing lag, and the queue metrics exposed by your SDK.
  • Reconnect only when the error can succeed on a new connection.
  • Reconcile after disconnects when missing a transaction would change application state.

Preserve transport security

The official Rust, Go, and Python SDKs validate the certificate chain and target hostname by default. They send the bearer token in the first control message after the secure connection opens. Keep the dashboard hostname in the target. Dialling a resolved IP without setting the original server name can break certificate validation. Private certificate authorities can be added without disabling normal validation: In Go, start with x509.SystemCertPool(), append the private CA, and pass the resulting pool to WithRootCAs when the client must trust both public and private roots. The insecure development options are limited to loopback targets. Do not use them with a production token. Pulse uses QUIC over UDP. ssh -L, HTTP proxies, and TCP-only tunnels do not carry the connection. Use a network path that preserves UDP.

Keep the receive path bounded

Backpressure signals differ by SDK: Decode or copy the minimum data needed in the receive task. Send CPU-heavy parsing, database writes, and network calls to bounded workers. An unbounded queue only turns a temporary slowdown into memory growth.

Understand the delivery boundary

Sig-first

QUIC datagrams can be lost, reordered, or duplicated. Use the signature as the deduplication key. A jump in seq can indicate loss, but reordering can make a high-watermark gap counter over-report. The sequence counter starts again at 0 on every connection. It cannot resume an earlier subscription.

Full-tx

QUIC preserves order and delivery for frames after Pulse enqueues them on the stream. A bounded server queue can shed a transaction before enqueue, so stream ordering does not imply an end-to-end lossless or at-least-once feed. Full-tx frames contain decoded transaction data observed from shreds. They do not prove that a transaction landed or reached a confirmation level.

Reconcile when correctness requires it

Wire v2 has no cursor, resume, retransmission, or backfill request. After a gap or disconnect, query ThorEdge RPC to rebuild any state your application cannot safely infer from the live feed. Choose the reconciliation key from the workload: signatures for transaction tracking, slots for range checks, or account state for stateful processors. Make reconciliation idempotent so reconnects and duplicate datagrams do not repeat side effects.

Handle application close codes

Read the QUIC application close code and reason before deciding to reconnect. Official SDKs expose this information as a typed error. Do not retry the same request after codes 1, 4, or 5. Code 2 requires a credential change. Code 3 is the only Pulse rejection that should be retried unchanged. The SDKs preserve this decision data instead of collapsing a server close into end-of-file:
Stop and surface an unknown Pulse application close code; do not guess that it is retryable. For a network interruption, reconnect a bounded number of times with backoff. If the failure continues, stop the loop and log enough redacted context to diagnose it.

Reconnect without creating a storm

Use one reconnect loop per intended feed:
  1. Close the old client and its workers.
  2. Classify the terminal error.
  3. Stop on a non-retryable close code.
  4. Apply exponential backoff with jitter to transient failures.
  5. Open a new connection with the same location target and current token.
  6. Restore the complete filter and enrichment selection.
  7. Reconcile the missing interval when necessary.
Cap the delay and the number of immediate attempts. Opening parallel replacement connections can consume more capacity and make a transient problem worse.

Change filters safely

A filter update replaces the include, exclude, require, vote, and enrichment values as one complete selection. Include every value you want to keep. After an accepted update, items already queued can still match the earlier filter. Design the consumer to tolerate a short overlap. If an update is rejected, the connection continues with the previous filter; log the reason and keep that earlier configuration as the active state.

Monitor the feed

Useful signals include:
  • Active connection and selected feed
  • Reconnect count and last close code
  • Time since the last transaction or idle heartbeat
  • Sig-first local drops, duplicates, gap signal, and queue depth where the SDK exposes it
  • Full-tx processing latency and stream errors; for Python, local queue depth and overflow
  • Reconciliation duration and unmatched records
Heartbeats are emitted when the feed is idle, not on a fixed schedule during busy traffic. Track both transaction traffic and idle heartbeats when choosing an application liveness threshold.

Troubleshoot common failures

For account-specific capacity, concurrent stream capacity, and current access status, read Usage and Limits in the dashboard instead of encoding a tier table into the application.

Next steps