Skip to main content
The AppDNA Flutter SDK is designed to work reliably in offline and poor network conditions. All offline logic is delegated to the native iOS and Android SDKs, which handle config caching, event queuing, and bundled fallback configs transparently.

Config Resolution Priority

When the SDK needs configuration data, it follows this priority order:
PrioritySourceDescription
1RemoteFresh config fetched from the AppDNA backend
2CachedPreviously fetched config stored on device
3BundledStatic config file shipped with the app binary
The SDK always attempts to fetch the latest remote config. If the network is unavailable, it falls back to the cached config. If no cache exists (e.g., on first launch with no connectivity), it uses the bundled config.

Config TTL

The configTTL option controls how long cached config is considered fresh before the SDK attempts to fetch a new version from the server:
await AppDNA.configure(
  "adn_live_xxx",
  environment: AppDNAEnvironment.production,
  options: AppDNAOptions(
    configTTL: 300, // 5 minutes (default)
  ),
);
ParameterTypeDefaultDescription
configTTLint?300Seconds before cached config is considered stale
When the TTL expires, the SDK will attempt to fetch fresh config on the next access. If the fetch fails, the existing cached config continues to be used.

Event Queue

Events tracked while the device is offline are stored in a persistent queue on the device. The queue is flushed automatically when connectivity is restored.

Queue Configuration

Control the flush behavior through AppDNAOptions:
await AppDNA.configure(
  "adn_live_xxx",
  environment: AppDNAEnvironment.production,
  options: AppDNAOptions(
    flushInterval: 30, // Seconds between automatic flushes (default: 30)
    batchSize: 20,     // Events per batch (default: 20)
  ),
);
ParameterTypeDefaultDescription
flushIntervalint?30Seconds between automatic event flushes
batchSizeint?20Number of events to batch before flushing

How the Queue Works

  1. Events are persisted to local storage immediately when track() is called.
  2. The SDK attempts to flush events either when the batchSize is reached or every flushInterval seconds.
  3. If a flush fails due to network issues, events remain in the queue and are retried on the next flush cycle.
  4. When connectivity is restored, all queued events are sent in order.
Events are never dropped due to network failures. The queue persists across app restarts, ensuring no data is lost even if the app is terminated while offline.

Bundled Config

To ensure the SDK has a valid configuration on first launch — even without network connectivity — you can bundle a static config file with your app.

iOS

Add the config file to your Xcode project bundle:
  1. Download the config bundle from the AppDNA Console under Settings > SDK > Config Bundle.
  2. Save it as appdna-config.json.
  3. Add it to your Xcode project by dragging it into the project navigator.
  4. Ensure the file is included in your target’s Build Phases > Copy Bundle Resources.

Android

Place the config file in the Android assets directory:
android/app/src/main/assets/appdna-config.json
  1. Download the config bundle from the AppDNA Console under Settings > SDK > Config Bundle.
  2. Save it as appdna-config.json.
  3. Place it at android/app/src/main/assets/appdna-config.json.
The bundled config is a snapshot. It will be used only when no remote or cached config is available. To keep the bundled config up to date, regenerate and replace it as part of your CI/CD pipeline before each release.

Config Bundle Version

The bundle version is managed by the native layer. When the SDK resolves config, it compares the cached config version with the remote version to determine whether an update is needed. The bundled config is treated as version 0 and is always superseded by any cached or remote config.

EventChannel Streams

The SDK uses Flutter EventChannels to stream real-time data from the native layer. These streams work across the full app lifecycle, including when the app transitions between foreground and background states:
EventChannelPurpose
com.appdna.sdk/web_entitlementWeb entitlement change stream
com.appdna.sdk/push_receivedPush notification received stream
com.appdna.sdk/push_tappedPush notification tapped stream
com.appdna.sdk/entitlementsEntitlement changes stream
EventChannel streams automatically reconnect when the app returns from the background. You do not need to re-subscribe to streams after lifecycle transitions.

Offline Behavior Summary

FeatureOffline Behavior
Event trackingEvents queued locally, flushed when connectivity restored
Remote configFalls back to cached config, then bundled config
Feature flagsUses cached/bundled values until remote config is refreshed
ExperimentsVariant assignments are cached; new assignments wait for network
Push registrationToken registration is retried when connectivity restored
PurchasesHandled by the native store SDK (StoreKit / Google Play Billing)

Best Practices

  1. Always bundle a config file for first-launch reliability.
  2. Keep configTTL reasonable — 5 minutes (default) balances freshness with network efficiency.
  3. Call flush() before background — While the SDK handles this automatically, explicitly flushing before the app enters the background provides an extra safety net.
  4. Do not assume network availability — Design your app UI to work with cached config values. Use onReady() to know when remote config has been loaded.
// Flush events before background
void onAppLifecycleStateChanged(AppLifecycleState state) {
  if (state == AppLifecycleState.paused) {
    AppDNA.flush();
  }
}