Only one platform puts a number on your startup time, and it is not Apple.
App startup time is how long it takes from the tap on your icon to a usable first screen. Android splits it into cold, warm and hot starts, measures the first frame as time to initial display, and Android vitals calls a cold start of 5 seconds or longer excessive. Apple measures the same thing and publishes no threshold at all, just a watchdog that terminates a launch which runs too long. Neither number is shown to the people browsing your listing, and on Google Play startup time is not a core vital, so it does not cost you discoverability. Every figure and field name below comes from Google's, Apple's, React Native's and Expo's own documentation, read on 10 October 2026. It is one slice of app performance, and the easiest slice to measure.
What follows is what each of the three starts actually involves, who is counting and what happens when you fail, the causes that are specific to shipping a JavaScript bundle, and the one command or pane that gives you a real number on each platform. The surprise is at the end of the second section. The thing that can kill your app for a slow launch is not a store at all.
Start hereThe short version
Five seconds cold is the only published line. Everything else is your own bar.
Android vitals is the only place in either store where a startup time becomes a number with a verdict attached. Google treats a cold startup of 5 seconds or longer, a warm startup of 2 seconds or longer and a hot startup of 1.5 seconds or longer as excessive, and says it can alert you on the Play Console when your app crosses them. That is a warning, not a penalty. Startup time sits outside the core vitals, which are the metrics Google says affect discoverability.
Apple does the measuring and skips the verdict. You get launch times from real devices in the Xcode Organizer and in MetricKit, with nothing published about a target. What Apple does enforce is responsiveness: a watchdog monitors launch times and kills apps that block the main thread for too long. So the honest summary is that nobody ranks you on startup time, one platform warns you, and both platforms will eventually stop waiting.
What counts as a cold, warm and hot start?
Android defines three, and the difference between them is how much of your app still exists when the user taps. A cold start is the app starting from scratch: the system creates the process, which is what happens on the first launch since the device booted, or since the system killed your app to free memory. A warm start does a subset of that work and still costs more than a hot one. The user backs out and comes back, so the process may survive but the activity is built again through onCreate, sometimes with a saved instance state bundle to help. A hot start is the cheap one: the system brings your host activity to the foreground, and if the UI is still resident in memory the app skips object initialization, UI initialization and rendering entirely.
Apple carves the same ground into two words instead of three. A launch is when the process needs to start. A resume is when your app already had a process alive, even if suspended, and Apple says a resume is generally much faster and that optimising the two is different work. The informal names map across: a relaunch straight after leaving the app is the fast case people call a warm launch, while coming back after a memory hungry game evicted you, or right after a reboot, is the cold one.
There is a second split that matters more than cold against hot, and it is the one people forget to measure. Time to initial display is the time to draw the first frame of your UI. Time to full display is the time until the app is actually usable, which includes content that loads asynchronously after that first frame. Android names both and gives you a way to mark the second: call reportFullyDrawn on your ComponentActivity, and the system reports the elapsed time from the launch intent to that call. A React Native app can easily have a good first number and a bad second one, because a skeleton screen draws fast and the data behind it does not.
Which one you are being judged on depends on who is doing the judging. Android vitals uses time to initial display, so a splash screen that appears instantly scores well even if the app is useless for another four seconds. Your users are judging time to full display. Pick the metric that matches the complaint you are trying to fix, and write the number down before you change anything.
Does either store measure or penalise a slow start?
Google measures it and tells you. Android vitals uses time to initial display, gathered from real devices in the field, and Google says it can alert you on the Play Console when your startup times are excessive. The thresholds are the three numbers above. That is the whole of the store involvement, and it stops there. Google sorts Android vitals into core vitals and everything else. The core vitals are user-perceived ANR rate, user-perceived crash rate, excessive battery usage for watch faces, and excessive partial wake locks, which is in beta. Those are the metrics Google says are the most important technically and affect the discoverability of your app on Google Play. Excessive app startup time is not one of them.
Apple measures it too, and publishes no verdict. The Xcode Organizer has a Launch Time pane showing the milliseconds between the tap on your icon and your first screen being drawn, after the static splash screen, from devices in the field. A Launches pane lists the longest running functions behind it. MetricKit gives your own code the same data as histograms: time to first draw, a separate one for prewarmed launches, one for resuming from the background, and one that includes extended launch tasks. None of it reaches your product page, and Apple says nothing about launch time affecting your position in the App Store.
The enforcement on iOS comes from the operating system instead, and it is blunt. Apple says the system employs a watchdog that monitors launch times and app responsiveness and terminates unresponsive apps, and that it terminates apps which block the main thread for a significant time. There is no single published limit. The worked example in Apple's own documentation shows a launch that exhausted a real, wall clock allowance of 19.97 seconds during scene creation, so the allowance in that case was just under 20 seconds. The practical consequence is a reporting one: a watchdog kill lands in your crash reports as a termination with Code 0x8badf00d, so slow launches show up in the same place as debugging a real crash, and get misread as one.
So the answer to the question nobody else answers: both platforms measure your startup time, one of them publishes a threshold, neither shows it to users, and neither says it moves your ranking. The real cost of a slow start is the person who taps once, waits, and leaves. That shows up in your retention numbers long before it shows up in a console.
Apple, reducing your app's launch time, read 10 October 2026
What makes a JavaScript app slow to start?
A React Native app has one extra step before anything appears: the JavaScript has to be loaded and run. Hermes is the default engine for new React Native apps and exists largely to make that step cheap. In release builds the JavaScript is fully compiled to bytecode ahead of time, and React Native says bytecode is loaded to memory on demand and does not need to be parsed the way plain JavaScript does. React Native also notes that using Hermes results in improved start-up time for many apps compared with JavaScriptCore. If you are on recent React Native you already have this, and the New Architecture is the wider change it arrived with.
That leaves the part Hermes cannot fix: how much of your code runs before the first screen. React Native names two tools for cutting it down. Screen level components can be deferred with React's lazy API, so that adding a new screen to your app does not increase its startup time. Individual modules can be deferred with an inline require call where you would otherwise write a static import at the top of a file, and the React Native CLI inlines require calls automatically, both in your own code and inside packages in node_modules. In an Expo project you turn that on by setting inlineRequires to true in getTransformOptions in the Metro config. RAM bundles are the older answer to the same problem and are not supported with Hermes, because Hermes bytecode is not compatible with the format and React Native says it performs as well or better anyway.
The native side of the list reads the same in a different language. Android calls out heavy app initialization, where your Application subclass does complex work on startup, and prescribes lazy initialization: only build the objects you need right now, and reach for a singleton created on first use instead of a global static. It calls out heavy activity initialization too, naming a large or complex UI, blocking the first draw on disk or network reads, loading and decoding bitmaps, and rasterising vector drawables. Every one of those has a React Native equivalent you have probably written: a provider stack that opens a database at the root, a font or image preload before the first render, an analytics SDK initialised at module scope. Fewer modules at launch also means a smaller bundle, which is why this work overlaps with app size.
The last cause is the one you control most directly and measure least. A held splash screen. Expo gives you preventAutoHideAsync to keep it up and hideAsync to take it down, and says the goal should be to hide the splash screen as soon as possible. If you hold it while an API call completes, your startup time is that request, and no amount of bundle work will move it. Load the shell first, show placeholder content, and fill it in when the data lands.
Find yours
Where your startup time is going
Tick what you are actually seeing. Each one has a different cause and a different place to look first.
Nothing ticked. If you have no symptom yet, measure before you optimise: a cold start you have never timed is not slow, it is unknown.
Which tool measures startup time on each platform?
On Android the cheapest measurement is already being printed. Search Logcat for a line containing Displayed, and the value beside your activity is the time to initial display. Android's own example shows a value of 3s534ms on an ActivityManager line. To force a comparable run, use adb shell am start with the -S and -W flags against your activity: -S stops the app first so you get a cold start every time, and -W makes the command wait and print ThisTime, TotalTime and WaitTime in your terminal. Read TotalTime. For time to full display, call reportFullyDrawn and watch for the Fully drawn line in Logcat. For the trace behind the number, open a Perfetto recording and find the row with the Android App Startups derived metric, which shows the duration of the startup in the current selection.
On iOS the field data comes first. Open the Xcode Organizer and read the Launch Time pane for milliseconds from the tap to your first drawn screen, after the static splash screen, then the Launches pane for the longest running functions inside it. To reproduce it on a device in front of you, use the App Launch template in Instruments, which gathers a time profile and a thread state trace. The Time Profile template shows the App Life Cycle timeline, which splits a launch into process initialization, UIKit initialization, UIKit initial scene rendering and initial frame rendering, so you can see which phase owns your seconds. MetricKit is how you get the same numbers into your own analytics instead of into Xcode.
Two rules make all of these honest. Measure release builds only: React Native says JavaScript thread performance suffers greatly in dev mode because much more work happens at runtime to produce good warnings and errors, and a debug build is served from Metro rather than from precompiled bytecode. And measure on the devices your users have, not the one on your desk, which is why the field data in Android vitals and in the Xcode Organizer beats any local run you can do. Local tools tell you why. Field data tells you whether it matters.
The same number, treated differently by each platform
| The question | Android and Google Play | iOS and the App Store | Same answer on both |
|---|---|---|---|
| What the platform measures | Time to initial display, TTID, the first frame of your UI | Time to first draw, after the static splash screen | No |
| A published excessive threshold | Cold 5s, warm 2s, hot 1.5s | None published | No |
| Reported back from real users | Android vitals, in the Play Console | Launch Time pane, in the Xcode Organizer | Yes |
| Counted against store discoverability | No, startup time is not a core vital | No, Apple publishes no such effect | Yes |
| Shown to the people browsing your listing | No | No | Yes |
| A hard kill for taking too long | No launch equivalent documented | Watchdog termination, Code 0x8badf00d | No |
| A command you can run locally today | adb shell am start -S -W | Instruments, App Launch template | No |
Where this lands if a builder generated your app
None of the measurement changes because an agent wrote the code. The numbers come from the same places, the thresholds are the same thresholds, and the work is still deciding what runs before the first screen. What does change is whether you can read and edit the files where that decision lives.
Newly is an AI app builder. You describe an app in plain English and it writes a real React Native and Expo project in TypeScript that you own, with two-way GitHub sync, so the Metro config, the splash screen calls and the provider stack at your root are all files you can open. It runs the app on cloud iOS and Android simulators while it builds, uploads iOS builds to TestFlight, publishes to Google Play internal testing and builds a standalone Android APK. It is $25 a month and there is no free tier. Because the project is a normal Expo project, Hermes bytecode in release builds and inlined require calls are the defaults you already get.
The honest limits are two. A generated app does not come with a startup budget, so the first time you add a font preload or an analytics SDK at module scope you own that cost like anyone else. And Newly does not submit to the App Store for you, because Apple requires the owner of the content to submit, which means the Launch Time pane in your own Xcode Organizer is where your field data will be. Measure a release build on the cheapest phone you can find, and fix the slowest phase first.
Questions people ask about app startup time
Android's own documentation draws all three lines. A cold start is the app starting from scratch, where the system creates the app's process, which happens on the first launch since the device booted or since the system killed the app. A warm start covers a subset of that work and still carries more overhead than a hot start: the user backs out and relaunches, so the process may still be running but the activity is recreated through a call to onCreate. A hot start is the cheapest, because the system brings your host activity to the foreground and, if the UI is still resident in memory, the app skips object initialization, UI initialization and rendering. Apple uses two words rather than three. A launch is when the process needs to start. A resume is when a process was already alive, even if suspended, and Apple says a resume is generally much faster and that the work to optimize the two differs.
Describe the app, then time the first screen
Get a release build on a real phone, read TotalTime once, and keep that number next to you. Everything after that is deciding what does not need to run yet.
Start building