Software Development

App efficiency starts with three fixes you can ship this sprint

By James KillickAugust 23, 2026

TL;DR: Three fixes do most of the work: turn on your build optimiser, batch and cache network calls, and stop redrawing UI that has not changed. Measure a baseline first, then check P95 startup and frame time on a cheap phone to prove the change held.

Most slow apps are not broken. They are just running with the handbrake on.

Three fixes do most of the work. Turn on your build optimiser. Batch and cache your network calls. Stop redrawing UI that has not changed. Do those three before you touch anything else.

But measure first. Always. A change that feels faster on your own phone is not proof of anything.

Here is the order we would work in:

  1. Turn on your build optimiser. On Android that means R8 full mode plus Baseline and Startup Profiles. Prove it with a macrobenchmark. Cold start before, cold start after.
  2. Batch and cache network calls. Group the requests that fire together. Delay the ones nobody is waiting on. Cache the rest with a clear expiry. Prove it by counting requests per session in your analytics.
  3. Stop redrawing what has not changed. Full re-renders on a scrolling list are the most common cause of stutter. Prove it with a frame trace over a normal scroll.

Peer-reviewed work on popular apps found that energy problems are common. They mostly come from background work and sloppy resource use, not exotic bugs. That is good news. Known problems have known fixes.

Then take one more measurement: P95 startup time, in the lab and out in the field. That single number tells you whether the sprint helped real people or just felt good.

Key takeaways

PointWhat it means
Measure before you change anythingGet a baseline for startup, frame time, memory and battery first.
Build settings come before feature codeR8, resource shrinking and Baseline Profiles pay off across the whole app.
Watch the tail, not the averageP95 and P99 show the worst moments. Those are the ones people remember.
Test on a cheap phoneBudget hardware exposes memory and CPU problems a flagship hides.
Cache after you fix, not instead of fixingCaching a slow query just hides it until the cache misses.
Guard the win with a budget in CISet a number, fail the build when it breaks, roll out behind a canary.

Which numbers actually matter

Startup time is where people form their first impression. It comes in three flavours.

  • Cold start. The system builds a brand new process. Slowest, and the one to fix first.
  • Warm start. The process is still around, but some state is gone.
  • Hot start. The app is already running and just comes back to the front.

There is no magic target number that fits every app. The goal is simple. Get something real on screen before the person gives up. Then close the gap between cold and warm starts so switching apps feels instant.

Frame rendering is next. Every frame gets a budget. About 16 milliseconds at 60Hz. About 11 at 90Hz. Miss the budget and people see a stutter, a skipped animation, a scroll that catches.

Here is the thing. The average frame time hides the problem. Look at the tail instead. P90, P95 and P99 tell you how bad the worst moments get. Those are the moments people remember, even when they are a tiny slice of all frames.

Memory is a quieter version of the same story. More memory pressure means more garbage collection. Those pauses look exactly like a rendering problem: dropped frames, jerky scroll, taps that do nothing. Push it far enough and the system kills your app, which the user reads as a random crash. So if you are chasing stutter and cannot find a drawing cause, check memory before you dig any further.

Battery and CPU round it out. Apple treats energy use as part of the experience itself, not a side issue bolted on later. Watch background CPU, wake locks and how often you hit the network while the app sits idle. People notice a flat battery faster than they notice a slow screen.

Rank the numbers by who they hurt:

  • Cold start P95 and P99. Slow starts drive uninstalls.
  • Frame time P95 and P99 on your busiest scroll. Tail stutter is what gets noticed.
  • Memory high-water mark on a cheap phone. That is where crashes cluster.
  • Background CPU and wake lock time. That is your battery complaint, in a number.

Fix whichever one sits furthest from your target. Not whichever is easiest to patch.

Five wins you can land this sprint

The fastest wins come from build settings, not business logic. They pay off across the whole app instead of one screen.

  1. Turn on R8 full mode and resource shrinking. Android's own guide treats R8, resource shrinking and Baseline Profiles as the standard path to a smaller, faster app. Full mode is aggressive and needs solid keep rules, so test a real release build before you ship it.
  2. Trim the bundle. Audit oversized images. Strip native libraries per ABI. Delete drawable variants nobody references any more. A smaller binary installs faster and does less disk work during a cold start.
  3. Batch and cache network calls. Group requests that fire together. Send only what changed instead of the whole object. Delay anything the current screen is not waiting on. Django's docs are blunt about the order of operations: fix the slow query first, then cache. Caching on top of a bad query just hides it until the cache misses.
  4. Stop invalidating views you do not need to. Reuse view holders. Give list items a fixed height where your framework allows it. Do not trigger a full layout pass for a partial update.
  5. Put risky changes behind a release toggle. Full R8, aggressive shrinking and library stripping can all break edge cases that only appear in production. Ship them behind a flag you can flip back in seconds.

Pro tip: run your before-and-after on the cheapest phone you officially support. Your dev phone hides the exact problems these fixes are meant to solve.

None of these five need a rewrite. That is the point. A tidy sprint can land all five, measure each one, and have hard numbers by Friday.

How startup, rendering, memory and network connect

Every fix belongs in one of five buckets. Matching a symptom to its bucket is what turns "the app feels slow" into a real job someone can pick up.

Startup is about clearing the critical path between process creation and the first useful frame. Audit what runs in your app's launch hook. Move anything the first screen does not need. Baseline and Startup Profiles pre-compile the code paths your app uses at launch, so the runtime is not reading them cold. Watch for screens that exist only to redirect to another screen. They cost a full lifecycle and give the user nothing.

Rendering is about doing less work per frame. React Native's own docs are upfront that framework abstractions are not enough on their own for demanding UI, and native work is often still needed to hold the frame rate. In practice: cut needless re-renders, give list items stable keys, and use fixed item sizes where the content allows it. Layout measurement is one of the most expensive parts of a render pass. Overdraw is worth a look too, where the GPU paints the same pixel two or three times because of stacked backgrounds.

Memory work starts with finding the hotspots, not guessing at them. A profiler shows you which code paths make the most garbage. The fix is usually fewer short-lived objects in hot loops, like scroll listeners and per-frame maths. Caching lives here as well. An oversized in-memory cache solves one problem and creates another, so size it against a cheap phone, not your laptop.

Network and data covers prefetching what the person will probably need next, caching it properly, and compressing payloads before they hit the wire. For web apps, edge caching moves content physically closer to the user, which cuts round-trip time before your code even runs. Google's PageSpeed tooling is a fine place to start auditing payload weight and render-blocking resources. If this is where your problem lives, it is really an architecture question, and the same scalability thinking applies.

Background work is where battery and performance overlap most. Batch and delay discretionary work so the device gets real idle time instead of waking up every few seconds. On iOS that means background task scheduling instead of polling. On Android, WorkManager gives you constraint-based scheduling, so a sync job can wait for a charger or Wi-Fi rather than firing on a timer. Set sensible quality-of-service levels so the system can push non-urgent work down the queue.

One problem though. Background scheduling logic grows teeth. If yours needs its own state machine to stay readable, that is a signal. Bringing in mobile app development specialists who have built the constraint logic before beats reinventing it in-house. The same goes for web app development when the bottleneck is really on the server side.

Which tools to profile with

Profiling only works if you follow a sequence. Opening a tool and staring at graphs is not a method.

  1. Reproduce it in the lab first. A macrobenchmark against a fixed build and device gives you a repeatable baseline. Change one thing. Run it again. Compare.
  2. Trace with Perfetto or your platform tools. Perfetto covers CPU tracing, memory and system-wide events on Android. On iOS, Xcode Instruments does the same job, with dedicated instruments for energy, time profiling and allocations.
  3. Use Simpleperf for native code. When the bottleneck sits in native libraries, it samples at system level and catches stack frames the managed profilers miss.
  4. Use the memory profiler for leaks and spikes. Watch for objects that live longer than they should.
  5. Add field telemetry once the lab fix looks solid. Frame vitals or a tool like Firebase Performance Monitoring show you what is happening on the long tail of real devices your lab cannot copy.

A single lab number never tells the whole story, which is why you pair lab and field:

Test typeWhat it showsWhen to use it
MacrobenchmarkRepeatable startup and scroll numbers on a fixed buildBefore and after a specific change
Frame metricsFrame timing spread across a sessionDiagnosing stutter on a specific screen
Field telemetryReal-world spread across your whole device fleetConfirming a lab fix helps real people
Cheap device testingWorst case under memory and CPU pressureExposing what flagship hardware hides

Structure every test the same way. Set a baseline, change exactly one thing, then measure P95 and P99 in the lab and again in the field. Test on a genuinely cheap phone on purpose. Worst-case hardware surfaces the problems a flagship will happily hide until your lowest-spec users start complaining.

Trade-offs worth watching

Faster is not always cheaper. Aggressive in-memory caching can cut load times on a flagship while quietly pushing a budget phone over its memory ceiling. That triggers the exact stutter you were trying to kill. So check every caching change against your lowest device tier, not your average one.

A few traps show up again and again:

  • Optimising code nobody touches. Profile first. Guessing at bottlenecks burns sprint time on screens people rarely open.
  • Sloppy R8 keep rules. Too permissive and you lose most of the benefit. Too strict and you break libraries that use reflection, often invisibly until a crash report turns up weeks later.
  • Caching with no expiry plan. You trade a speed win for a stale-data bug. Django's docs say it plainly: caching is not a substitute for fixing the slow thing underneath.
  • Shipping a fix you never measured. "Feels faster" is not evidence. Measure the same number before and after, every time.

Rank candidate fixes by impact over effort. How many people does this touch, how bad is the effect, and how much engineering time does it cost? Cheap devices and your busiest user journeys sit at the top of that list almost every time. That is where a fix reaches the most people who are currently having the worst time.

Then stop the win from rotting. Write a performance budget as a number in your CI config. Fail the build when it breaks. Roll bigger changes out to a small slice of users before everyone gets them.

Pro tip: put the budget in CI, not in a Slack message. "Cold start under 1.5 seconds on the reference device" is enforceable. "Try to keep it snappy" is not.

How to ship performance work safely

Run it in four steps, whatever the platform. Profile the current state against real device tiers and real user journeys. Set the baseline numbers and the targets before any code changes. Build the fixes behind release toggles. Then re-run the same lab and field measurements against that original baseline and check the win actually held once real users hit it.

A short checklist helps, kept visible and enforced at code review rather than left as a good intention:

  • A performance check on every pull request touching startup, rendering or background work.
  • Release-only toggles for anything that changes build settings, so a regression is a flag flip and not a rollback.
  • A dashboard tracking P95 and P99 startup and frame time in production, not just in the lab.
  • Sign-off on the performance budget before a release, not after a complaint.

Plenty of this an in-house team can run solo. Where outside help usually pays is at scale: rolling Baseline Profiles across a multi-module codebase, setting one performance standard across iOS and Android, or untangling background scheduling that grew wild over several years. It is the same discipline behind good system integration, and the same reason prototypes fall over in production when nobody set a number to hit.

Good performance work is rarely one big rewrite. It is a stack of small, measured, reversible changes that compound, each one checked against a number you took before you shipped it.

Ready to build an app that is fast from day one?

Retrofitting speed into an app that was never built for it is slower and riskier than building the discipline in from the first sprint. Devwiz has shipped 200+ apps and platforms since 2015, for clients including the NSW Government, Briometrix, Vivid and Huskee.

If you are planning a new build, or you want a team to take an existing app through a proper performance overhaul, our AI app development team can scope it. Profiling, baseline, then shipped and measured improvements. Worth knowing the cost of building an app before you start, too.

Tell us where your app sits today and we will map what a prioritised sprint looks like for your platform and your users.

Frequently asked questions

What makes an app efficient?

An efficient app starts fast on cold, warm and hot launches. It holds frame times inside budget at P95 and P99, keeps memory low enough to avoid heavy garbage collection, and does little background CPU or network work when it is idle.

What are examples of app efficiency improvements?

Turning on R8 full mode and Baseline Profiles for a faster start. Batching and caching network calls instead of firing them one at a time. Cutting needless re-renders in scrolling lists.

How do you improve an app's performance?

Measure a baseline first with a macrobenchmark and field telemetry. Then apply build settings, resource shrinking and caching, and check each change against P95 and P99 before moving to the next one.

How can I check my app's performance?

Use lab tools like Perfetto, the memory profiler and Simpleperf for traces. Pair them with field telemetry such as frame vitals so you see how real devices behave, not just your test phone.

Why does battery use matter for app performance?

Wasted energy usually comes from background work and poor resource use, and it hits battery life directly. Research on popular apps found these problems are common rather than rare, and people notice a flat battery fast.

About James Killick

10+ years building digital products · 200+ apps shipped since 2015

James is a co-founder of Devwiz and an AI product specialist. Since 2015 he has helped ship 200+ apps for founders, businesses and government, including work for NSW Government, Briometrix and Huskee. He builds AI-first platforms and writes about turning a proven program into software. He also hosts the Up in the AI podcast.

More articles by James · James's personal site · LinkedIn · AI Orchestrators

Tags: App Development, Performance, Mobile

Browse all Devwiz articles·See our case studies