Mobile app performance

Techniques and tools to make your app fast, efficient and pleasant to use on any device

10 min

Performance is the factor that most impacts mobile app retention. A Google study shows that 53% of users abandon an app if it takes more than 3 seconds to load. Performance issues affect not only the experience but directly impact business metrics, store ratings and organic ranking.

Optimising mobile performance is an ongoing process covering startup time, memory consumption, battery usage, network efficiency and interface fluidity. This guide covers the most effective techniques and the essential tools for diagnosing and resolving bottlenecks.

Startup time (cold start)

Cold start is the time from when the user taps the app icon until the first screen is interactive. Apple recommends it be under 400ms and kills apps that exceed 20 seconds. Google measures TTID (Time To Initial Display) and TTFD (Time To Full Display) as official metrics.

The most common causes of slow cold starts are: heavy SDK initialisation on the main thread, blocking remote data loading, splash screens masking actual load time, and synchronously resolved dependencies. The solution involves deferring non-critical service initialisation, pre-caching essential data and using lazy loading.

  • Target: < 1 second for cold start on mid-range devices
  • Defer SDKs: initialise analytics, ads and non-critical services after the first frame
  • Pre-warm: use background fetch to have data ready before the user opens the app
  • Baseline profiles (Android): AOT-compile critical paths for faster startup

Memory management

Mobile devices have limited memory. When an app consumes too much RAM, the OS kills it to free resources (OOM kill). This results in unexpected crashes, especially on low-end devices that represent the majority of the global market.

Memory leaks are the most insidious problem: objects that should be freed but retain strong references preventing the garbage collector from reclaiming them. On iOS, retain cycles (circular references between objects) are the most frequent cause. On Android, Activities retained after onDestroy by unremoved listeners or callbacks.

  • Detect leaks: Xcode Instruments (Leaks/Allocations) on iOS, Android Profiler in Android Studio
  • Images: resize before display, use compressed formats (WebP, HEIF), release when off-screen
  • Long lists: use RecyclerView (Android) or UICollectionView with diffable data source (iOS) to recycle cells
  • Weak references: use weak/unowned in closures (Swift) and WeakReference on Android to avoid retain cycles

Battery consumption

Excessive battery drain is one of the top reasons for uninstalls. The biggest consumers are: continuous GPS, frequent server polling, constant animations, unnecessary wake locks and unoptimised background processing.

To reduce battery impact, use location services only when necessary (at the minimum accuracy required), replace polling with push notifications or WebSockets, batch network requests to take advantage of the radio when it’s already active, and respect the system’s battery saving modes.

  • Location: use significant location changes instead of continuous GPS
  • Network: batch requests and use push instead of polling
  • Background: limit background tasks to what is strictly necessary
  • Monitoring: Battery Historian (Android) and Energy Impact in Xcode for diagnostics

Network efficiency

Mobile connections are unstable, with variable latency and limited bandwidth. A well-designed app should work reasonably well on 3G (or even offline) and make the most of fast connections when available.

Key techniques include: aggressive HTTP caching with ETags, payload compression (gzip/brotli), list pagination, progressive image loading (thumbnails first, full resolution later), and request deduplication to prevent duplicate requests when users navigate quickly.

  • HTTP cache: implement ETags and cache-control headers correctly
  • Compression: gzip/brotli for APIs, WebP/AVIF for images
  • Pagination: load data in batches, not the entire dataset at once
  • Retry with backoff: exponential retries for failed requests

Interface fluidity (60/120 fps)

The minimum fluidity standard is 60 fps (16.6ms per frame). Devices with high-refresh displays (ProMotion, 120Hz) require 8.3ms per frame. Any operation that blocks the main thread for longer causes jank: dropped frames that users perceive as sluggishness or lag.

The most common causes of jank are: complex layout recalculations, rendering uncached shadows and gradients, overdraw (painting pixels that are immediately overwritten), and I/O operations on the main thread. The golden rule: the main thread should only handle rendering; everything else goes to background threads.

  • Main thread: rendering only, never I/O, networking or heavy processing
  • Overdraw: reduce stacked layers, use opaque backgrounds where possible
  • Shadows and corners: cache rasterisation on iOS (shouldRasterize), use elevation on Android
  • Lists: cell prefetching, cell reuse, avoid layout inflations during scroll

Profiling and monitoring tools

Profiling is essential for data-driven optimisation, not intuition-based. Each platform offers powerful tools: Xcode Instruments (iOS) analyses CPU, memory, energy, network and frame-by-frame rendering. Android Studio Profiler covers CPU, memory, network and energy with real-time visualisation.

For production monitoring, Firebase Performance Monitoring tracks startup times, custom traces and slow HTTP requests. Sentry and Datadog offer crash and performance monitoring with configurable alerts. The fundamental principle is to measure on real devices, not just simulators.

  • Xcode Instruments: CPU, memory, leaks, energy, rendering profiling (iOS)
  • Android Studio Profiler: real-time CPU, memory, network, energy (Android)
  • Firebase Performance: production monitoring, traces and network traces
  • Flipper (Meta): cross-platform debugging for React Native and native apps

Continuous optimisation strategy

Performance optimisation is not a one-off event but an ongoing process. Establish a performance budget (maximum acceptable times for startup, transitions, network response) and measure it in CI/CD with automated tests. Tools like Maestro and Detox allow measuring rendering times in continuous integration pipelines.

Prioritise optimisations by user impact: one second less on cold start has more impact than saving 5MB of RAM on a high-end device. Always test on low-end devices (the ones your actual users own), not just the latest iPhone or Pixel.

  • Performance budget: define maximum thresholds for key metrics
  • Low-end testing: performance problems surface on budget devices
  • CI/CD: integrate performance benchmarks into the test pipeline
  • Continuous monitoring: automatic alerts when metrics exceed thresholds

Key Takeaways

  • Cold start should be under 1 second on mid-range devices
  • Memory leaks cause silent crashes: use profiling tools regularly
  • Excessive battery drain is one of the top reasons for uninstalls
  • The main thread should only handle rendering: everything else in the background
  • Measure on real low-end devices, not just simulators or flagships
  • Optimisation is a continuous process with performance budgets in CI/CD

Is your app suffering from performance issues?

We diagnose your application’s bottlenecks and apply the optimisations that improve the real experience for your users.