Skip to main content
The AppDNA SDK is designed to work reliably in offline and low-connectivity environments. Configuration is cached locally, events are persisted to disk, and a bundled fallback config ensures the SDK functions even on first launch without network access.

Config Resolution Priority

The SDK resolves configuration using a three-tier priority system:
PrioritySourceDescription
1 (highest)RemoteFirestore real-time listener for live configuration
2CachedUserDefaults-backed cache with TTL-based expiration
3 (lowest)BundledStatic appdna-config.json included in the app bundle
The SDK uses a stale-while-revalidate pattern. Cached config is served immediately while a fresh copy is fetched from the remote source in the background.

Config TTL

The cached configuration has a time-to-live (TTL) that defaults to 300 seconds (5 minutes). You can customize this value in AppDNAOptions:
AppDNA.configure(
    apiKey: "adn_live_xxx",
    environment: .production,
    options: AppDNAOptions(configTTL: 600) // 10 minutes
)
When the TTL expires, the SDK fetches a fresh config from Firestore on the next access. The stale config continues to be used until the fresh config is received.

Config Update Notifications

Listen for config updates using NotificationCenter:
NotificationCenter.default.addObserver(
    forName: AppDNA.configUpdated,
    object: nil,
    queue: .main
) { notification in
    print("Config updated — refreshing UI")
    // Re-read remote config values and update UI
}

Bundle Version

Check the current config bundle version:
let version = AppDNA.currentBundleVersion // Int
print("Current config bundle version: \(version)")

Bundled Config

For first-launch scenarios or environments with no network access, include a static configuration file in your app bundle:
  1. In the AppDNA Console, navigate to SDK > Config Bundle.
  2. Download the appdna-config.json file.
  3. Add the file to your Xcode project, ensuring it is included in your app target’s Copy Bundle Resources build phase.
MyApp/
  Resources/
    appdna-config.json    <-- Add this file
The bundled config is a snapshot and will become stale over time. Always ensure the SDK can reach the remote config source for the latest configuration. The bundled config should be treated as a fallback only.

Event Queue

Events tracked with AppDNA.track(...) are not sent immediately. They are queued locally and flushed in batches.

Queue Behavior

SettingDefaultDescription
flushInterval30sTime interval between automatic flush cycles
batchSize20Number of events to batch before auto-flushing
Events are flushed when either condition is met (whichever occurs first).

Persistence

Events are persisted to disk immediately when tracked. This ensures that:
  • Events survive app crashes and force quits.
  • Events survive app restarts and device reboots.
  • Events are delivered on the next successful flush after connectivity is restored.
The event queue is stored in the app’s documents directory. Events remain queued until they are successfully delivered to the AppDNA backend or the user revokes analytics consent.

Retry Policy

When a flush attempt fails, the SDK retries with exponential backoff:
AttemptDelayDescription
11sFirst retry after initial failure
22sSecond retry
34sThird and final retry

Error Handling

Status CodeBehavior
2xxSuccess. Events removed from queue.
4xxClient error. Events discarded immediately (no retry).
5xxServer error. Events kept in queue and retried.
Network errorEvents kept in queue and retried on next flush cycle.
Events that receive a 4xx response are discarded permanently. This prevents malformed events from blocking the queue. Check your event schemas if you see 4xx errors in the SDK logs.

Network Timeouts

OperationTimeout
API requests30s
Resource downloads60s
When analytics consent is set to false:
AppDNA.setConsent(analytics: false)
Events are silently dropped and are not added to the queue. No data is stored or transmitted. When consent is later granted, only events tracked after that point are queued and sent.
Consent state is persisted. If a user revokes consent and restarts the app, the SDK remembers the revoked state and continues to drop events until consent is explicitly granted again.

Secure Storage

The following data is stored in the iOS Keychain for security:
DataStorageDescription
Push tokensKeychainAPNs device token
User IDsKeychainIdentified user ID
Anonymous IDsKeychainAuto-generated anonymous identifier
Keychain storage ensures these values persist across app reinstalls and are protected by the device’s hardware encryption.

Summary

ConcernBehavior
Config on first launchBundled appdna-config.json used as fallback
Config cachingUserDefaults with configurable TTL (default 300s)
Config freshnessStale-while-revalidate; Firestore real-time listener
Event persistenceWritten to disk immediately, survives crashes and restarts
Event flushAutomatic on timer (30s) or batch threshold (20 events)
RetryUp to 3 retries with exponential backoff (1s, 2s, 4s)
4xx errorsEvents discarded, no retry
5xx / network errorsEvents retained, retried on next flush
Consent revokedEvents dropped silently, not queued
Sensitive dataStored in Keychain (push tokens, user IDs, anonymous IDs)