Slow mobile app — how to find the cause and speed it up

Slow startup, long loading, stutters and freezes — how to measure app performance in Android vitals and Xcode Organizer, which causes we see most often, in what order to fix them and how long it takes.

Zespół Mobilesoft· Engineering team· 28 października 2026· 11 min czytania

"Takes forever to load", "stutters when scrolling", "gets slower and slower after a few minutes" — reviews like these rarely point to a single bug. A slow app is usually the sum of several problems that built up over the years: new features, more libraries, bigger images, more data from the server. Each change was small on its own; together they make an app people use reluctantly or not at all.

Performance affects revenue more than it seems. A user who waits several seconds for an app to start is more likely to close it, less likely to finish a purchase and more willing to leave a low rating. On Android, poor performance also directly affects visibility on Google Play.

This article explains how to find out what exactly is slowing your app down, which causes we see most often, and in what order to fix them.

What "slow" means

Before you look for the cause, name the symptom. "Slow" can mean five different problems, each with a different source:

  • Slow startup — several seconds pass between tapping the icon and the first usable screen.
  • Slow data loading — the screen appears, but its content takes a long time to load, or a spinner keeps spinning.
  • Stuttering (jank) — scrolling and animations aren't smooth; the app "jerks".
  • Freezes — the app stops responding to touch for a second or longer. On Android, after 5 seconds the system shows an "App isn't responding" dialog (ANR).
  • Slowing down over time — a freshly launched app works fine, but after a quarter of an hour it gets slower or crashes.

Users describe the first two as "takes forever to load" and the other three as "it lags". That's why reviews alone aren't enough — you need measurements.

Step 1: measure before you fix

The most common mistake is optimising by gut feeling: someone rewrites a piece of code that "must be slow", and the app runs exactly as before. Start with the data you already have for free:

  • Android vitals in Google Play Console — startup time (cold, warm and hot start), ANR rate, slow and frozen frames. The data comes from real users and is broken down by phone model and OS version.
  • Xcode Organizer (iOS) — launch time, hangs, memory and battery usage, also from real users.
  • Firebase Performance Monitoring or Sentry — load times of individual screens and API response times as seen from the phone.

Rough thresholds above which it's worth acting:

Metric Where to check When it's a problem Cold start Android vitals, Xcode Organizer Android treats 5 s or more as excessive; on iOS, aim for the first frame within 0.4 s Warm / hot start (Android) Android vitals 2 s or more / 1.5 s or more ANR (Android) Android vitals above 0.47% of daily users — Google Play's bad behaviour threshold Frozen frames Android vitals, Sentry frames taking longer than 700 ms to render Hangs (iOS) Xcode Organizer main thread blocked for 250 ms or longer API response time Firebase Performance, Sentry, backend logs when the 95th percentile exceeds 1–2 s on key screens

Pay attention to the breakdown by device. An app that runs beautifully on a new iPhone and a flagship Samsung may be barely usable on cheaper Android phones — and there are a lot of those. If the team only tests on its own new phones, this problem stays invisible.

Only once you know which screen and which devices are the problem should you reach for detailed analysis tools: the Android Studio profiler and Perfetto, Instruments in Xcode (Time Profiler, Allocations, Leaks), Flutter DevTools or the React Native profiler.

The most common causes

Symptom Common cause Typical fix Slow startup many SDKs initialised at launch, synchronous requests before the first screen lazy initialisation, Baseline Profiles, a first screen that doesn't wait for the network Slow screen loading slow API, many requests instead of one, no caching backend fix, combined requests, caching and pagination Slow images, high data usage full-resolution photos, no image cache server-side or CDN thumbnails, WebP/AVIF, a caching library Stuttering while scrolling heavy work on the main thread, inefficient lists moving work to the background, proper lists and item keys Freezes, ANRs database writes, JSON parsing or file operations on the main thread asynchronous code, StrictMode for detection Slowing down over time memory leaks, a growing in-memory cache memory analysis, fixing screen lifecycles Slow on older phones an old framework or engine, animations that are too heavy framework update, simpler effects

The details of the ones we see most often follow below.

Slow app startup

Startup is the first impression and the one moment when the user definitely waits. In older apps it usually looks like this: a dozen libraries initialise at launch — analytics, ads, chat, remote config, crash reporting, partner SDKs — and only then does the first screen appear. On top of that, the app waits for a server response before showing anything.

What helps:

  • Initialise only what the first screen needs. Start the rest later, or only on first use. A chat used on one screen doesn't have to start with the app.
  • Don't wait for the network before showing a screen. Show the last saved data or a skeleton screen, and load fresh data in the background.
  • On Android, add Baseline Profiles. This is a list of code the system compiles ahead of time at install. According to Google, it speeds up code execution by around 30% from the very first launch — for relatively little work.
  • Remove unused libraries. In apps developed over many years, we regularly find SDKs nobody uses any more that still slow down startup and inflate the app size.

Network and backend: often not the app's fault

A large share of "slow apps" are actually slow APIs. The phone shows a spinner because it's waiting for the server — and no amount of app code optimisation will change that.

Typical communication problems:

  • Many requests when opening a single screen. The order screen fetches the order, each product, the address and the delivery status separately — a dozen requests, each with mobile network latency. A single request returning everything the screen needs can cut loading time several times over.
  • No pagination. The list fetches every record at once. With 50 records in the MVP days that wasn't a problem; with 5,000 it is.
  • No caching. The app fetches the same data every time the screen opens, instead of showing what it saved and refreshing it in the background.
  • Slow database queries on the server. Missing indexes, or queries that grew along with the database. This shows up in the backend logs, not in the app.

That's why API response times are worth measuring from both sides: from the phone (Firebase Performance, Sentry) and from the server. If the server responds quickly but the phone sees long times, the problem is the network, the response size or the number of requests.

Images

Photos are the most common cause of slow loading in shopping, restaurant and classifieds apps. The classic case: the server sends a product photo at its original size — 4,000 pixels wide and several megabytes — and the app displays it as a 200-pixel thumbnail in a list.

The fix usually doesn't require big changes in the app: the server or CDN generates several sizes of each photo in a modern format (WebP or AVIF), and the app downloads the one that fits the screen. Add an image caching library — Coil or Glide on Android, Kingfisher or SDWebImage on iOS, cached_network_image in Flutter — so the same photo isn't downloaded again on every scroll.

Stutters and freezes: work on the main thread

An app's interface is drawn on a single main thread. For an animation to be smooth at 60 frames per second, each frame has to fit in about 16 ms — and in half that on 120 Hz screens. If the app writes to its database, parses a large JSON file or runs a complex calculation during that time, the frame is late and the user sees a stutter. When such an operation takes several seconds, Android shows an ANR.

The most common sources:

  • database and file operations performed on the main thread,
  • parsing large server responses on the UI thread,
  • lists that recalculate or rebuild every item on each scroll (in Jetpack Compose and SwiftUI — missing stable keys and views refreshing too often),
  • heavy visual effects: shadows, blurs and transparencies layered on top of each other.

On Android, StrictMode in development builds helps catch these problems — it flags disk and network operations on the main thread. If the app has a lot of old view code, consider a gradual migration to Jetpack Compose and SwiftUI for the most frequently used screens.

Memory leaks

If the app works well after launch but slows down or crashes after a quarter of an hour, the most common cause is memory leaks: screens that aren't released after being closed because something still holds a reference to them — an event listener, a timer, a data subscription. Memory grows, the system cleans up more and more often, the app slows down, and eventually the system kills it.

This is one of those problems you don't see in short tests. LeakCanary on Android, Instruments (Leaks, Allocations) on iOS and the memory data in Xcode Organizer all help. Out-of-memory terminations are also worth tracking in your crash monitoring — they often show up there as crashes with no obvious cause in the code.

An old framework and old libraries

Cross-platform apps from a few years ago are often slower not because of bugs in the code, but because of the framework version:

  • React Native — since version 0.70 the default JavaScript engine is Hermes, and since 0.76 the New Architecture is the default. An app on the old engine and the old architecture starts more slowly and struggles more with smoothness.
  • Flutter — the new Impeller rendering engine eliminated the typical stutter the first time an animation is shown. It has been the default on iOS since Flutter 3.10 and on Android since 3.27.

In such cases, a framework update alone can deliver more than weeks of manual optimisation. Updating after years is a project in itself, though, and is worth planning together with testing.

In what order to fix things

  1. Measure where you are — Android vitals, Xcode Organizer, key screen times. Write the numbers down so you can compare them after the changes.
  2. Pick the two or three most important screens — startup, product list, cart, payment. Improving a screen 90% of users see is worth more than polishing the settings screen.
  3. Start with the quick wins — image sizes, caching, lazy SDK initialisation, combined requests, Baseline Profiles. They often deliver most of the effect.
  4. Then main-thread work and memory leaks — these require profiling, but they eliminate stutters and ANRs.
  5. A framework update or rebuilding screens — if the measurements show that the technology, not specific pieces of code, is the bottleneck.
  6. Make sure it doesn't come back. Add startup and key screen timing to your release process — on Android, the Macrobenchmark library does this and can run in CI/CD.

Release fixes gradually and compare the new version's metrics with the previous one. Better results should show up in Android vitals and Xcode Organizer within a few days of release.

How long it takes

Stage Rough time Measurement and diagnosis (performance audit) 3–5 days Quick wins: images, caching, startup, combined requests 1–2 weeks Main thread, lists, memory leaks 1–3 weeks, depending on the number of screens Framework update or rebuilding key screens several weeks or more, a separate project

If performance is just one of many problems — the app is also unstable, hard to develop and built on outdated libraries — it's worth taking a broader look and deciding whether a refactor or a rewrite makes more sense.

Summary

A slow app rarely has a single cause. Most often it's a combination of several: too many libraries starting with the app, a slow or poorly used API, full-resolution photos, work on the main thread and an old framework. Start with the measurements Google and Apple provide for free, pick the most important screens, and fix things starting with the changes that give the most for the least effort. Better performance usually also means a better store rating.

If your app is slow and you don't know where to start, request a free app analysis — we'll check your Android vitals and Xcode Organizer data and point out what slows it down the most. We run detailed code and performance reviews as part of our audits and consulting, and ongoing care as part of our mobile app maintenance service.