4. Offline delivery
Phones lose connectivity and apps are killed. Telemetry has to survive both without arriving twice.
4.1 The queue
Section titled “4.1 The queue”- 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).
4.2 Batches
Section titled “4.2 Batches”- 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).
4.3 Record ids
Section titled “4.3 Record ids”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.uidon every log record.
4.4 Upload scheduling
Section titled “4.4 Upload scheduling”- 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
URLSessionon 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 omitsApsio-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.
4.5 Deduplication on the backend
Section titled “4.5 Deduplication on the backend”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-Idper 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.idas one crash.