Skip to content

4. Offline delivery

Phones lose connectivity and apps are killed. Telemetry has to survive both without arriving twice.

  • MUST write records to a queue on disk before sending them, and send what is left on a later launch.
  • MUST cap the queue’s size. When the cap is reached, the SDK drops the oldest batches first, except crash, exit and session summary records, which it drops last. Attachments go before any batch (1.7).
  • MUST drop a batch older than 7 days (a policy value) instead of sending it.
  • MUST drop the whole queue when the app withdraws consent (section 13) or the policy’s kill switch is on (section 12).
  • MUST give each batch an Apsio-Batch-Id (section 1.2), generated when the batch is sealed.
  • MUST NOT re-batch records after the first send attempt. A batch is immutable once sealed: a retry resends the same bytes with the same batch id.
  • SHOULD seal a batch when it reaches the size limit (section 1.4), when the app moves to the background, or after a short interval in the foreground (a few seconds to a minute).

Each record carries an id, kept for audit and as a backstop to batch deduplication:

Signal Record id
Log records and events log.record.uid: a random id generated when the record is created (a UUID or ULID)
Crash events app.crash.id as well, the same across every attempt to report one crash
Spans trace_id + span_id
Metric points The series identity (name, Resource, attributes) plus start and end time
  • MUST set log.record.uid on every log record.
  • SHOULD send with a regular HTTP session while the app is in the foreground.
  • SHOULD hand what is left to the platform’s background transfer when the app moves to the background: a background URLSession on Apple platforms, a WorkManager job on Android. Large uploads (crash reports, replay) SHOULD always use that path. An upload the operating system sends on the SDK’s behalf omits Apsio-Sent-At; a WorkManager job runs SDK code and sets it (section 5.1).
  • SHOULD respect the user’s data and battery settings (Low Data Mode, Data Saver, Low Power Mode), deferring non-urgent uploads.

Delivery is at-least-once. A backend:

  • MUST store a batch once, whatever the number of times it is received, by remembering each Apsio-Batch-Id per app for at least the queue’s maximum age (7 days).
  • MUST answer a duplicate with 200 (section 1.5).
  • SHOULD use the record ids in 4.3 to drop duplicates that reach it under different batch ids, for example from an SDK that violated the no-re-batching rule.
  • MUST treat two crash events with the same app.crash.id as one crash.