Skip to content
useffect.sh
Book 30 min with a senior
Performance

Cold start (startup time)

Launching the app from scratch, process included: native init, bundle load, first React render, up to a usable screen (TTI).

Definition

A cold start is launching an app when its process does not exist yet: the first launch since the phone rebooted, or a relaunch after the system killed the app. Android distinguishes cold start from warm start (process alive, Activity to recreate) and hot start (everything still in memory), and measures two milestones: Time To Initial Display (TTID), the first frame drawn, and Time To Full Display (TTFD), the screen actually usable, which the app signals with reportFullyDrawn. For a React Native app, cold start stacks native startup (dyld and initializers on iOS, Application on Android), creation of the Hermes runtime, loading and executing the bundle, then the first React render and the first requests. What teams call TTI (time to interactive) maps to TTFD. Android vitals measures it in the Play Console and flags excessively slow cold starts.

In a real app

Measurement comes before any optimization, and only on release builds. On Android, adb shell am start -W and the Displayed line in logcat give TTID; reportFullyDrawn (callable from a native module once the screen is ready) gives TTFD. On iOS, the App Launch template in Instruments splits pre-main (dynamic framework loading, static initializers) from post-main. On the JavaScript side, performance.mark and the Performance panel in React Native DevTools show the time between bundle execution and the first React commit. A real low-end Android device is the reference, not the simulator.

The usual causes, in the order I find them: module-level work (SDK initialization, storage reads, large image requires) executed before the first render; a bundle that loads every screen when inline require or lazy-loaded routes could defer them; a cascade of blocking network requests behind the splash; heavy Intl polyfills; and on iOS a dynamic use_frameworks! that multiplies the frameworks loaded at pre-main. Hermes and its bytecode solve the parsing part, not these five.

What I look at first in a project: what runs between index.js and the first screen, how many providers are nested at the root, and whether the splash is hidden on a precise event (data ready) rather than a timer.

Our services on this

Sources

All 35 glossary terms

One of these is blocking your app?

30 minutes with a senior to look at the problem in your code. Free.