Cold Start — Cold Launch and Optimization in Android

Author: IT Sectr Published: 2026-03-31 Reading time: 9 min

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 — launching an Android app from scratch: new process, class loading, initialization
  • Metric measured from process start to first draw (TTID or TTFD)
  • Phases of startup: process creation → Application.onCreate → Activity.onCreate → first frame
  • Optimization includes lazy initialization, Baseline Profiles, and reducing DEX size
  • Google Play uses Cold Start as one of the key metrics in Android Vitals

What Is Cold Start

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.

When Cold Start Occurs

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.

Why Cold Start Is a Critical Metric

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.

Cold Start vs Warm Start vs Hot Start

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 TypeProcess StateApplication.onCreateTypical Time
ColdNo processExecuted1–5 seconds
WarmProcess exists, no ActivityNot executed200–600 ms
HotProcess + Activity in memoryNot 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.

Transition Between Types

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 Launch Phases

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.

Phase 1: Process Creation (fork)

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.

Phase 2: Application.onCreate

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.

Phase 3: Activity.onCreate

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.

Phase 4: First Frame (TTFD)

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.

How to Measure Cold Start

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.

Measurement via ADB

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).

bash
# 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

Android Vitals (Google Play Console)

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.

Macrobenchmark

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.

How to Optimize Cold Start

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.

Lazy Initialization

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

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.

App Startup Library

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.

kotlin
// 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" />

Reducing DEX Size

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.

Cold Start in Android Vitals

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 Thresholds

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).

How Google Play Uses the Metric

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%.

Integration with Firebase Performance

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).

Code Examples for Optimization

Below are two practical examples that directly accelerate Cold Start: moving SDK initialization after startup and using the SplashScreen API.

Moving Initialization from Application.onCreate

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.

kotlin
// ❌ 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()
}

SplashScreen API

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.

kotlin
// 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

Why is Cold Start faster on an emulator than on a device?

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.

What Cold Start is considered acceptable?

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.

Does the icon size affect Cold Start speed?

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).

Is it necessary to optimize Cold Start in Feature Modules?

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.

How does Multidex affect Cold Start?

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

  • Cold Start — full app launch with new process creation, time 1–5 seconds
  • Measured via ADB shell am start -S -W or Macrobenchmark in CI/CD
  • Four phases: fork → Application.onCreate → Activity.onCreate → first frame
  • Optimization: lazy initialization, Baseline Profiles, App Startup Library, R8 compression
  • Google Play rates Cold Start as “bad” when time exceeds 5 seconds on any device
  • SplashScreen API on Android 12+ hides initialization time behind a system splash
  • Every 100 ms of delay reduces user retention by 3%

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.

Discuss the project

Read also