Cold Start is the complete launch cycle of an Android application, starting from a zero state when the app’s process does not exist in memory and the Activity has not been created. The system creates a new process, loads classes, initializes the Application, creates the Activity, and performs the first draw. According to Google, 2024, cold start on mid-range devices can take 1 to 5 seconds, and every 100 ms of delay reduces user retention probability by 3%.
Key Takeaways
Cold Start is a scenario where an Android application launches from the very initial state: the operating system creates a new process (fork from Zygote), allocates memory, loads DEX code into ART, initializes classes, and creates an Application instance, then the first Activity. Before the app launches, there is no data about it in device memory, except for cached class images if Background Dexopt is used.
Cold launch happens in three cases: on the first launch after app installation, on launch after device reboot, and on launch after the system has evicted the process due to low memory. On devices with 2–4 GB RAM, the system evicts background processes quite aggressively, so Cold Start can occur every time the user returns to the app after several hours of inactivity. On Android 12+, the system can keep a frozen process (freeze / cached), but with active memory saving (OOM-killer), the process will be killed.
According to Google (Find My Device report, 2023), 65% of users close an app if it does not open within 3 seconds. For social networks and messengers, where users return dozens of times a day, Cold Start directly affects retention. In Google Play Console, the Cold Start metric is part of the Android Vitals section and is displayed as one of the ANR and performance indicators. An app that exceeds the “bad” Cold Start threshold (more than 5 seconds on 25% of devices) receives a warning in the console and may be demoted in search results.
Android distinguishes three types of app launch, each with different duration, UX impact, and optimization approaches. Understanding the difference is essential for choosing the right profiling strategy.
| Launch Type | Process State | Application.onCreate | Typical Time |
|---|---|---|---|
| Cold | No process | Executed | 1–5 seconds |
| Warm | Process exists, no Activity | Not executed | 200–600 ms |
| Hot | Process + Activity in memory | Not executed | < 200 ms |
Warm Start occurs when the app process already exists in the background, but the Activity has been destroyed (e.g., the user returned after a long pause and the system freed the Activity memory). Hot Start — when the user minimizes the app and immediately opens it again: the Activity is paused and restoration takes minimal time. For the user, Cold Start is the most noticeable launch type, and optimizing it gives the greatest UX improvement.
Cold Start can become Warm Start after the app has been launched at least once — ART caches compiled class images (Image in Boot Profile) and subsequent DEX loading is faster. Therefore, the second launch after the first Cold Start is usually 20–40% faster. If the app uses Baseline Profiles, profiles are loaded on the first launch and the second start can be even faster: Google Play, which published Baseline Profiles, accelerated Cold Start by 30% on devices with Android 12+.
Cold Start consists of strictly defined phases, each of which can be measured and optimized independently. Knowing the phases helps determine at which stage the app is losing time. Google identifies four main phases: process creation, Application initialization, Activity creation, and the first frame.
The Android system (ActivityManagerService) creates a new process by forking from the Zygote process. Zygote is a pre-loaded process with common Android classes. Fork takes 30–80 ms — this time is beyond the app’s control. After fork, ActivityThread starts — the main loop instance of the application. At this stage, class loading also occurs through ClassLoader, and ART begins interpreting the first bytecode. If the app uses many static initializers, this phase can be prolonged.
Immediately after ActivityThread starts, Application.onCreate is called. This is where developers most often make a mistake by initializing everything at once: Crashlytics, Firebase, network clients, databases, Dagger components, DI containers. Each such initialization is time blocked on the main thread. If Application.onCreate takes 500 ms, the user sees a white (or black) screen for half a second. The optimal duration for this phase is less than 200 ms on a mid-range device.
After Application initialization, an Activity instance is created (MainActivity or Launcher Activity). Activity.onCreate is called, where setContentView, fragment initialization, ViewModel setup, and LiveData/Flow subscription occur. If onCreate loads data (SharedPreferences, SQLite, API) synchronously on the main thread, the phase extends. The goal is to fit onCreate within 200–400 ms on a mid-range device.
After onCreate completes, the first rendering begins: measure, layout, draw. This moment is called TTFD (Time To First Draw). If the app uses a splash screen (via SplashScreen API on Android 12+ or via theme), rendering may happen faster, but the user will still wait until the splash disappears. The ideal TTFD for Cold Start is less than 1.5 seconds.
Measuring Cold Start requires special tools, since regular logging (Log.d) only starts working after Application creation, and fork timing and class loading remain inaccessible. Google recommends three methods: ADB commands, Android Vitals, and custom perf macros.
The simplest and most reproducible method is the adb shell am start -S -W command. The -S flag forcibly stops the app before launch (ensures Cold Start). The command outputs three metrics: ThisTime (Activity start time), TotalTime (total time including process launch), and WaitTime (time including all Activity Manager delays). For clean measurements, take 5–7 readings and use the median — single readings are subject to noise (CPU throttling, background load).
# Forced Cold Start with measurement
$ adb shell am start -S -W \
com.example.app/.MainActivity
# Command output:
# ThisTime: 1842 ms
# TotalTime: 1842 ms
# WaitTime: 1855 ms
Google Play Console collects anonymous metrics from all devices where the app is installed. In the Android Vitals → Launch time section, the median Cold Start distribution by device model and Android version is displayed. This is the only way to see real metrics on user devices, not just test devices. If Cold Start exceeds 5 seconds on Redmi 9A (2 GB RAM) and 1.2 seconds on Pixel 8, the problem is memory size and class count. Google also shows user-perceptible delay based on the 25th percentile.
Google Jetpack Macrobenchmark (androidx.benchmark library) allows writing instrumented app launch tests. The test installs the app, launches it from a cold state, and measures the time to the first frame. Macrobenchmark automatically runs 20 iterations, discards outliers, and shows stable percentiles. For CI/CD, you can compare baseline and current launch times — if time increases, the CI pipeline can fail.
Optimizing Cold Start is systematic work that affects several levels of the app: code, resources, build configuration, and initialization architecture. Google recommends starting with the most expensive part — Application.onCreate — and moving to smaller details.
Move all initialization that is not required at startup out of Application.onCreate to the first point of use. Firebase, Crashlytics, analytics SDK, push-notifications, DI components — everything can be initialized after the first screen is rendered. Use Lazy (by lazy) in Kotlin or ContentProvider initialization with an explicit initialize(context) call. According to Google (Android Performance, 2023), lazy initialization reduces Cold Start by 40–60% for apps using 5+ SDKs.
Baseline Profiles are AOT compilation of critical classes and methods used at app startup. Without Baseline Profiles, ART interprets DEX code or compiles it via JIT, which takes time. With profiles, ART compiles the specified methods into native code (AOT) during app installation. Google states that Baseline Profiles accelerate Cold Start by 15–40% on Android 9+ and up to 60% with Android 12+ ART optimizations. To create profiles, use the androidx.benchmark:benchmark-baseline-profile-gradle-plugin plugin.
The androidx.startup library allows ordering component initialization and running it in a single ContentProvider. Instead of multiple ContentProviders from different libraries (each adding 1–2 ms to cold start), App Startup merges them into a dependency graph and initializes strictly on demand. At startup, only components marked with @Initializer that are required for the first screen are executed. For others, the needEarlyInit = false flag is set — they launch after the first render.
// App Startup Initializer — initialization after launch
class AnalyticsInitializer : Initializer<Unit> {
override fun create(context: Context) {
Analytics.init(context)
}
override fun dependencies() = listOf<Class<out Initializer<*>>>()
}
// In AndroidManifest.xml mark as optional
// <meta-data android:name="AnalyticsInitializer"
// android:value="false" />
DEX file size directly affects ART loading time. Use R8/ProGuard for obfuscation and dead code removal (MinifyEnabled = true). Enable android:extractNativeLibs="false" in the manifest so the APK does not unpack .so files on installation. For projects with 10+ reference tracking, add startup-priority only for the first screen. Each extra method in DEX adds 0.5–2 ms to loading, and for apps with 50k+ methods (multidex with primary dex) — up to 300 ms.
Android Vitals in Google Play Console (Launch time section) collects data from all devices where the app is installed, provided the user has consented to anonymous diagnostics. Metrics are divided into three categories: “good”, “moderate”, “bad”, depending on Cold Start time.
Google defines “bad” Cold Start as time exceeding 5 seconds on any device. However, in practice, for flagship devices (Snapdragon 8 Gen), a good time is less than 1.5 seconds, for mid-range — less than 2.5 seconds, for budget — less than 4 seconds. Android Vitals shows the median for each device model, allowing you to understand which devices have slow startup. If Cold Start is bad on Samsung A-series or Xiaomi Redmi devices, the cause is most often slow flash memory and low RAM (acceleration via Baseline Profiles yields the greatest effect precisely on such devices).
In addition to displaying in the console, the Cold Start metric affects the app quality rating in Google Play Search. Apps with a high percentage of “bad” startups receive a “Performance warning” label on the installation page, reducing conversion. According to Google (Android Performance Playbook, 2024), apps that resolved Cold Start issues increase installation conversion by an average of 5% and improve retention (D1) by 3–7%.
For more detailed monitoring, use Firebase Performance Monitoring. It tracks Cold Start at the session level, breaking it down by app version and Android version. Unlike Android Vitals, Firebase shows a trace diagram of time spent by phase. For example, you can see that on version 3.2.0, Application.onCreate took 800 ms (due to a new push notification library), while on version 3.2.1 — 200 ms (after the fix).
Below are two practical examples that directly accelerate Cold Start: moving SDK initialization after startup and using the SplashScreen API.
A typical mistake is initializing all SDKs in Application.onCreate. Below shows how to move non-critical initialization to a coroutine that launches after the first frame is drawn. Important: Firebase, Crashlytics, and Crash Reporting SDKs must be initialized at startup — they cannot be deferred because they catch crashes during initialization of other components. For the rest, use lifecycleScope in the first Activity.
// ❌ Bad — all initialization in Application.onCreate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this) // critical
Analytics.init(this) // can be later
Database.init(this) // can be later
ImageLoader.init(this) // can be later
}
}
// ✅ Good — Firebase at startup, rest after inflate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this)
}
}
// In MainActivity after the first frame:
lifecycleScope.launchWhenResumed {
initializeNonCriticalSdks()
}
On Android 12+, use the official SplashScreen API, which shows a system splash (app icon on a dark/light background) immediately when the process starts. This hides the initialization time from the user — they see a splash instead of a white screen. For older devices, use theme-based splash (Theme.SplashScreen in styles). Important: the splash should not last longer than 300 ms — if the app is not ready by then, draw a “persistent” skeleton (shimmer) and show loading progress.
// SplashScreen API — Android 12+
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition {
isReady.value == false
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
// Theme-based splash (Android 5-11)
// In themes.xml:
// <style name="Theme.App.Starting" parent="Theme.SplashScreen">
// <item name="windowSplashScreenBackground">@color/white</item>
// <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
// </style>
Frequently Asked Questions
The emulator uses a powerful host computer and emulates the processor with hardware acceleration (HAXM / WHPX). Physical devices, especially budget ones (eMMC storage instead of UFS), have much slower I/O. It is recommended to measure Cold Start on a physical mid-range device to get realistic data.
According to Google recommendations, the median Cold Start should be less than 2 seconds on mid-range devices. For flagships — less than 1.5 seconds. For budget devices (2 GB RAM), up to 4 seconds is acceptable, but optimization to 3 seconds is recommended. Values over 5 seconds are considered critical.
Indirectly — yes. If the manifest contains a vector icon (AdaptiveIcon), it must be compiled into a drawable at startup. If the icon contains complex paths (pathData with dozens of curves), compilation takes 10–30 ms. Use VectorDrawable with optimized pathData (via SVGOMG or Android Studio Vector Asset).
Yes, if a Feature Module (Android App Bundle) is loaded on-demand, its Cold Start is measured from the moment the feature is tapped to the first frame. On-demand modules are loaded via Play Core Library, and their installation adds 500–3000 ms to startup time. Optimize the feature code the same way as the main module.
Apps with more than 64k methods require Multidex. This means ART must load multiple DEX files, increasing Cold Start time by 200–800 ms depending on the number of classes.dex files. Use minSdk 21+ (ART with native multidex support) and configure primary dex via --main-dex-list to keep critical classes in the first DEX file.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also