Mobile SDKsOffline & Batching

Offline & Batching

The Datafly mobile SDKs are designed offline-first. Events are always persisted to a local SQLite database before any network request is attempted. This ensures zero data loss even when the device has no connectivity.

How it works

Event captured

Written to SQLite (immediate, synchronous)

Flush triggered? ─── No ──→ Wait for next trigger

    Yes

Network available? ─── No ──→ Wait for connectivity

    Yes

Batch events (up to 500, max 500KB)

POST to /v1/batch

Success? ─── No ──→ Retry with exponential backoff

    Yes

Delete events from SQLite

Flush triggers

Events are uploaded when any of these conditions are met:

TriggerDefaultConfigurable
TimerEvery 30 secondsflushInterval / flushIntervalSeconds
Threshold20 events queuedflushThreshold
ManualCall flush()
Network restoredAutomatic

Offline queue

  • Storage: SQLite database (WAL mode on iOS for concurrent access)
  • Maximum size: 1000 events (configurable via maxQueueSize)
  • Overflow behaviour: When the queue is full, the oldest events are dropped to make room for new ones
  • Crash recovery: On SDK init, any events left in “uploading” state are reset to “pending”

Batch transport

Events are uploaded in batches to the /v1/batch endpoint:

  • Maximum batch size: 500 events
  • Maximum payload size: 500 KB
  • Large batch splitting: If a batch exceeds 500 KB, it is automatically split into smaller batches
  • Authentication: Bearer token using the pipeline key
  • Deduplication: The server deduplicates events by messageId (UUID per event) via Redis

Retry policy

Failed uploads are retried with exponential backoff and jitter:

AttemptBase delayWith jitter (0-50%)
11s1.0 — 1.5s
22s2.0 — 3.0s
34s4.0 — 6.0s
48s8.0 — 12.0s
516s16.0 — 24.0s
632s32.0 — 48.0s

Non-retryable status codes

The SDK does not retry requests that return:

Status codeReason
200Success (no retry needed)
400Bad request (payload issue, retrying won’t help)
401Unauthorised (invalid pipeline key)
403Forbidden (pipeline disabled or IP blocked)

All other status codes (including 429 Too Many Requests and 5xx Server Error) are retried.

Network monitoring

The SDK monitors network connectivity using platform APIs:

  • iOS: NWPathMonitor (Network.framework)
  • Android: ConnectivityManager with NetworkCallback

When connectivity is lost, upload attempts are paused. When connectivity is restored, a flush is triggered immediately.

Force flush

Call flush() to immediately upload all queued events:

// iOS
Datafly.shared.flush()
 
// Android
Datafly.flush()

Common use cases for force flush:

  • Before app termination or backgrounding (for critical events)
  • After a purchase or conversion event
  • When the user explicitly logs out

App lifecycle events (Application Backgrounded) are tracked automatically. The SDK does not automatically flush on background — events remain safely queued in SQLite and are sent on the next foreground or flush trigger.

Configuration

let config = DataflyConfig(
    pipelineKey: "dk_live_abc123",
    endpoint: "https://data.example.com",
    flushInterval: 15,       // Flush every 15 seconds
    flushThreshold: 10,      // Flush after 10 events
    maxQueueSize: 5000       // Store up to 5000 events offline
)