A monitoring SDK that degrades the experience it measures defeats its own purpose. This page describes the SDK's execution model, identifies where it consumes resources, and covers the settings that control that consumption.

Execution model

The SDK's resource profile follows directly from how an event reaches Atatus:

  1. The event is captured on the thread where it occurred, performing only the work needed to record its fields.
  2. It is handed to a background executor, serialized, and appended to a batch file on disk.
  3. Batches are uploaded when network availability and battery level permit.

Serialization, persistence, and upload all execute off the main thread, so event capture does not contend with frame rendering. Uploading in batches rather than per event also keeps the radio in a low-power state between transmissions, which is what dominates the energy cost of network activity on mobile.

Where the SDK consumes resources

Area Characteristic
APK size A few hundred kilobytes after R8 shrinking, varying with the features you enable.
Memory A bounded working set. Events are flushed to disk rather than accumulated in memory.
CPU Short bursts on a background thread during serialization and upload.
Disk Bounded batch storage, with expired batches evicted automatically.
Network Periodic compressed uploads, sized by your batch and upload frequency settings.
Startup A few milliseconds in Application.onCreate() to initialize the SDK.
Note:

Treat these as directional and measure against your own build. Actual cost scales with the event volume your application produces, which depends on screen count, request rate, and error frequency rather than on the SDK itself.

Reduce the footprint

Sample sessions

Session sampling is the highest-leverage control, because it reduces event volume at the source and lowers CPU, disk, and network cost proportionally:

copy
icon/buttons/copy
val rumConfiguration = RumConfiguration.Builder()
    .setSessionSampleRate(25f)
    .build()

The decision is made once per session, so retained sessions remain complete. You trade population coverage for volume, not fidelity within a session.

Tune batching

Batch size and upload frequency trade data latency against radio use. Larger, less frequent batches amortize each radio wake-up across more events:

copy
icon/buttons/copy
val configuration = Configuration.Builder(licenseKey, env, variant)
    .setBatchSize(BatchSize.LARGE)
    .setUploadFrequency(UploadFrequency.RARE)
    .build()

Use LARGE with RARE when battery consumption is the constraint. Use SMALL with FREQUENT during development, where fast feedback matters more than efficiency.

Narrow the collection surface

Each of these reduces work before it is performed rather than discarding it afterwards:

  • Scope tracedHosts to the APIs you actively monitor, so the interceptor skips the rest.
  • Raise the long task threshold above 100 ms if the default yields more events than you act on.
  • Leave trackBackgroundEvents disabled unless background execution is part of what you measure.
  • Discard known-noisy events with an event mapper.

Keep R8 enabled

The SDK ships consumer ProGuard rules, so R8 shrinking and obfuscation apply without additional configuration and keep the size contribution at its minimum. Pair this with mapping file uploads so release traces remain readable.

Measure the impact yourself

To quantify the cost against your own application:

  1. Produce two release builds, identical except for the SDK integration.
  2. Compare APK size using the Android Studio APK Analyzer.
  3. Compare cold start with adb shell am start -W <package>/<activity>, averaged over several runs.
  4. Compare CPU and memory across a representative user flow using the Android Studio Profiler.

Exercise the same flow on both builds. Differences in navigation path or request volume will dominate the SDK's contribution and invalidate the comparison.

Next steps