How to Reduce Cold Start Time in a Mobile App Without a Full Rewrite

A smartphone home screen showing a grid of app icons

A user taps your app icon. For two or three seconds, nothing happens except a blank screen or a splash logo. Most of them will wait, this time. A meaningful number will not, and the ones who don't rarely file a bug report. They just quietly use the app less, or delete it after the third slow launch in a row. Cold start time is one of the few performance metrics that costs you users before they've seen a single pixel of actual product.

The instinct when a team finally notices this is to reach for a full rewrite: new architecture, new framework, sometimes a full platform migration. That's rarely the right first move, and it's almost never the fastest one. Most cold start problems are a handful of specific, fixable bottlenecks hiding inside an app that is otherwise perfectly fine. This piece walks through how to find them and fix them without touching the parts of your app that already work.

A smartphone held in a hand showing an app loading screen
Photo by Beyzanur K. on Pexels

Why Cold Start Time Quietly Kills Retention

"Cold start" specifically means launching the app from a fully terminated state, not resuming from the background. It's the worst-case launch, and it's also the one that happens most often for infrequent users, which is exactly the group a slow app is most likely to lose permanently.

The retention math is unforgiving. A user who opens your app weekly and hits a three-second cold start every time has a materially worse impression of your product than the engineering team does, because the team's own devices are usually newer, warmer (app already partially cached), and tested on better networks than a large share of the real install base. What feels acceptable on a flagship phone with a fresh battery can feel broken on a two-year-old mid-range device with forty other apps competing for the same limited memory.

Cold start is also one of the few performance metrics users experience before your app has done anything to earn their patience. A slow search result or a laggy scroll happens after they've committed to using the app in that session. A slow cold start happens before the first screen renders, when the cost of quitting is lowest and the user hasn't invested anything yet.

What's Actually Happening Between Tap and First Frame

Before optimizing anything, it helps to know what a cold start actually contains, because "the app is slow to open" describes at least four different phases, each with different fixes.

Process creation. The operating system allocates a new process and loads the app binary and its dependencies into memory. This phase is mostly outside your direct control, but binary size and the number of dynamic libraries you link against both affect it.

Application initialization. Your Application (Android) or AppDelegate (iOS) class runs, along with every SDK and library that hooks into app startup. This is the phase teams have the most control over and, in practice, the phase where most of the fixable time actually lives.

First activity or view controller creation. The initial screen's view hierarchy gets built and measured, including any data it needs synchronously before it can render.

First frame rendered. The point users actually experience as "the app opened." Everything before this is invisible to them except as elapsed time.

Most teams that say "our app is slow to launch" have never actually measured which of these four phases is the expensive one, and end up optimizing the wrong thing entirely.

Measuring Cold Start Before You Touch Any Code

Don't guess. Both major platforms ship tools that break a launch down into the phases above, and starting there saves you from optimizing something that was never the bottleneck.

On Android, Android Studio's built-in CPU profiler and the am start -W shell command both report a TotalTime for app launch, and macrobenchmark tests can isolate cold start regressions in CI before they reach users. On iOS, Apple's developer tools include Instruments' App Launch template, which breaks a launch down by phase and flags which specific initializers and dynamic library loads are contributing the most time.

Run these on a mid-tier device, not the newest phone in the office. A cold start that measures fine on the team's test hardware can be genuinely bad on the median device in your actual install base, and the gap between those two numbers is usually where the real user complaints come from.

Once you have a baseline, set a specific target (many teams aim for under 2 seconds on a mid-tier device) and measure every change against it, rather than optimizing by feel.

Trim What Runs Before the First Screen Paints

The single highest-leverage fix is almost always the same: audit everything that runs during application initialization and ask, honestly, whether it needs to block the first frame.

A startlingly common pattern is analytics, crash reporting, feature flag fetching, remote config, and A/B testing SDKs all initializing synchronously on the main thread before the first screen even begins building. None of these need to complete before the user sees something on screen. They need to complete before the user does something that depends on them, which is a much later point in the session.

A practical rule: anything that isn't required to render the very first screen the user sees should not run synchronously during application startup. Move it to run after first frame, on a background thread, or lazily on first use.

Defer Non-Essential SDK and Network Initialization

Third-party SDKs are the most common source of unnecessary cold start weight, because each one is individually small but they add up, and because teams rarely audit them together as a group.

Go through your dependency list and classify each SDK into one of three buckets: required before first frame (rare), required before first user interaction (most), and required only for specific features (defer until that feature is actually used). Push everything in the second and third buckets out of the synchronous startup path.

Network calls deserve the same scrutiny. A remote config fetch or a session-initialization API call that blocks rendering means your app's cold start time now includes a full network round trip, which on a mediocre connection can dwarf everything else combined. Cache the previous config locally and render with that first, fetching the fresh version in the background for next time. Firebase's performance monitoring tooling is a reasonable starting point for surfacing which specific network calls and traces are actually eating startup time in a shipped build, rather than guessing from local testing alone.

A stopwatch on a plain surface showing elapsed time
Photo by Stas Knop on Pexels

Shrink the App Binary and Its Dependency Graph

Process creation time scales with how much has to be loaded before your code even runs, so binary size and dependency count matter independently of what your initialization code does.

Dead code elimination, resource shrinking, and removing unused dependencies all reduce the amount of work the OS does before your Application class runs at all. This matters more on Android, where dynamic library loading at process start is a measurable cost, but it's not negligible on iOS either, particularly for apps that have accumulated dependencies over several years without anyone auditing whether they're all still needed.

This is also where "just add one more analytics SDK" quietly compounds. Individually each addition is a rounding error. Collectively, a few years of unaudited dependency growth is a real and measurable chunk of cold start time that nobody remembers agreeing to pay.

Server rack with organized cables in a data center
Photo by Winston Chen on Unsplash

Cache and Prefetch Without Blocking the Main Thread

The first screen a user sees usually needs some data, and how you get that data matters as much as whether you fetch it at all.

The pattern that works: render the first screen immediately from cached or default data, then update it once fresh data arrives. This means the user sees something meaningful within the first frame or two, rather than a spinner that blocks until a network call resolves. A feed screen can show yesterday's cached posts instantly and swap in fresh ones a moment later; a dashboard can show the last known values with a subtle "updating" indicator instead of an empty loading state.

This requires slightly more state management than "fetch, then render," but the perceived performance difference is large, and it's the difference between an app that feels instant and one that feels like it's making the user wait on purpose.

Cross-Platform Frameworks Add Their Own Startup Tax

If your app is built on a cross-platform framework, that layer adds its own initialization cost on top of the native platform's, and it's worth understanding separately rather than lumping it in with "app startup" generically.

Frameworks that bundle a JavaScript engine or a separate runtime typically need that runtime initialized, the bridge to native code established, and often an initial bundle parsed and executed, all before your first screen can render. This tax is real but it's also well documented and actively optimized by the framework maintainers, so checking your framework version and its release notes for startup-specific improvements is often cheaper than trying to work around the problem yourself. React Native's own documentation, for one, publishes specific guidance on trimming bridge initialization cost as the framework has matured.

"The teams that fix cold start fastest are the ones that stop treating it as one problem. It's four or five separate bottlenecks stacked together, and usually only one or two of them are actually worth your engineering time this quarter." - Dennis Traina, founder of 137Foundry

Whichever framework you're on, the profiling advice from earlier still applies: measure the framework's own startup phase separately from your application code's phase, so you know which one to spend your time on.

A tablet showing an app store style grid interface
Photo by Luis Quintero on Pexels

Monitoring Cold Start in Production, Not Just on Your Dev Phone

A fix that looks good in a local profiling session can still regress in production, because production has device diversity, real network conditions, and real data volumes that a dev environment rarely replicates faithfully.

Production monitoring for cold start time should track at least the median and a high percentile (p90 or p95) separately, because the median tells you how the typical user experiences your app and the tail tells you how your worst-case users experience it, and those two numbers can move in opposite directions after a change that helps the common case but regresses on low-memory devices. Tools like Sentry's mobile performance monitoring or your platform's own crash-and-performance reporting can track this automatically once instrumented, flagging regressions before they show up as a wave of one-star reviews mentioning "app takes forever to open."

Treat a cold start regression the same way you'd treat a crash rate regression: something that gets caught in CI or a canary rollout, not something you find out about from an app store review three weeks later.

Where This Fits Into a Broader Performance Practice

None of the fixes above require a rewrite. They require an honest audit of what runs before the first frame, a willingness to defer or remove anything that doesn't need to be there, and enough production monitoring to know whether the changes actually held up outside your own test devices.

Teams that treat cold start as a one-time cleanup usually see it creep back within a year, as new SDKs and features get added without anyone re-auditing the startup path. The teams that hold the gains are the ones that make startup time a metric they watch continuously, the same way they'd watch crash rate or API latency, rather than a problem they fix once and forget.

If your team wants a second set of eyes on where your app's launch time is actually going, 137Foundry's web development service works through exactly this kind of performance audit for production mobile and web applications. You can see the rest of the services we offer or read more about how we work on the 137Foundry homepage.

Need help with Web Development?

137Foundry builds custom software, AI integrations, and automation systems for businesses that need real solutions.

Book a Free Consultation View Services