App Size: More Than a Number
Every feature we ship adds something to the codebase: new logic, new assets, new strings. And with each addition, the application binary grows. While users get new functionality and engineers get to solve new problems, the cost of that growth is often overlooked. The best-case scenario is a silent tax on every user; the worst case is lost installs and a larger carbon footprint.
Talking about app size isn't as simple as quoting a single figure. There are actually four distinct measurements to consider:
- Download size: The compressed data transferred when a user fetches the app from a store.
- Install size: The uncompressed data written to disk immediately after installation.
- Storage size: The install size plus caches (images, audio, etc.) accumulated during use.
- Update size: The data transferred when downloading a new version; typically smaller than the full download size, depending on the delta.
These different sizes affect users in two main ways: network usage and device storage. While modern devices in developed markets can mask these issues, the global reality is different. A large portion of users in emerging markets rely on devices like the iPhone 6s with only 16GB of storage, a chunk of which is already occupied by the OS. Since these markets represent the vast majority of the world's population, app size is a critical factor for global reach.
The Tangible Cost of Every Kilobyte
The impact isn't just theoretical. Google's own experiments with artificially inflated app builds showed that every 6MB increase in app size resulted in a 1% drop in installation conversion rates. That's a direct, measurable loss of potential users tied directly to the weight of the binary.
There's also an environmental angle that's easy to miss. The sheer volume of app updates generates staggering amounts of network traffic. In 2022, Spotify's apps were updated over 20 billion times. At that scale, even a small download size accumulates into a massive data transfer total—more than 930 petabytes annually.
Those bytes consume energy. Using the Shift Project's one-byte model, transferring data over Wi-Fi consumes roughly 1.52e-10 kWh per byte. Even in an optimistic 100% Wi-Fi scenario, that annual update traffic translates to about 150,000,000 kWh of power. Based on EPA data, that's approximately 65,000 tonnes of CO2—equivalent to 65,000 round-trip flights between London and New York. Conversely, reducing our app size by just 1MB would cut our annual carbon footprint by an estimated 560 tonnes. Making apps smaller is both a user experience improvement and a sustainability measure.
Safety Nets in the Development Pipeline
To prevent uncontrolled bloat, we've integrated size checks into our CI process. Every pull request triggers a comparison between a base build (current master) and a head build (master plus the PR's changes). Both are processed by Emerge Tools, and the resulting diff report is posted directly to the PR.
Figure 1: Pre-merge app-size check flow.
This automated check enforces a clear threshold: PRs with a size increase under 50KB can be merged without additional review. Changes exceeding this limit are blocked and require approval from a dedicated team that evaluates the trade-offs.
Post-merge visibility is equally important. A dedicated Slack channel tracks every merged PR that crosses the threshold. This isn't just an alert system for regressions—it also celebrates wins. PRs that successfully reduce app size by more than the same 50KB threshold are also surfaced, giving teams positive feedback on their optimization efforts.
Attributing Growth to Owners
Thresholds catch the big jumps, but the thousands of small PRs that fly under the radar accumulate into significant bloat over time. To fight this snowball effect, we've implemented a different analysis: compile-unit attribution.
Instead of a diff between two builds, we analyze a single recent master snapshot. The build is uploaded to Emerge, which returns a detailed breakdown of how much each compilation unit contributes to both download and install size. We augment this data with resource file sizes collected through internal scripts.
This data is then grouped by module, and since each module has a dedicated owner team, we can precisely attribute the contributions. The results are presented in a dashboard that lets each team visualize their size footprint over time.
Figure 3: Backstage visualization of the team’s contribution to the application size.
The interface also provides comparative statistics, showing each team how their size contribution stacks up against others across the organization. This transparency creates accountability and helps maintain a balance between feature development and keeping the app lean.
Figure 4: Comparison of the team’s contribution with the average among Spotify teams.
Why Size Optimization Is Hard
Telling developers to write smaller code is easy; doing it well is not. There are three fundamental reasons why size optimization is a constant struggle.
First, it's a zero-sum trade-off. Refactoring to reduce binary size often pushes the cost elsewhere—usually into performance or architectural complexity. Code that's smaller might be slower or harder to maintain, and frequently, that trade-off isn't worthwhile.
Second, the source of bloat isn't always the code itself. Often, it's a quirk of the language runtime or the operating system. Addressing these issues might require restructuring the app in ways too extreme to justify.
Third, sometimes the size increase is simply unavoidable. A large, complex feature by its nature requires code, and that code has weight. No amount of optimization can avoid adding bytes when the feature requires them.
The Exception Process
Recognizing that some regressions are justified, we've established an App Size Policy. This document outlines why we care about size, explains the monitoring systems in place, and provides platform-specific optimization tips.
Most importantly, it defines an exception process. If a developer believes their PR's size increase is justified, they can follow this process to get approval. In most cases, the exception requires demonstrating a clear, positive business impact from the proposed change that outweighs the cost of the added bytes.
Measuring What Matters
To confirm the tooling was actually earning its keep, the team put together dashboards and a set of metrics that get monitored on an ongoing basis.
But the real-world impact isn’t limited to CI warnings and dashboard graphs. The dedicated Slack channel now gets a steady stream of app-size questions, and the team noticed that engineers are actively opting to shrink their PRs. The measured side effect is significant: an estimated 20MB of cumulative size reduction across all PRs.
The Trade-Off Is Now Visible
Growing the app is nearly unavoidable when you’re shipping new features. What you can control is how deliberate you are about it. With the right guidance, real-time monitoring, and alerting in place, the team can now make informed calls on whether a new feature is worth its footprint — and spot the occasional feature that shaves off size from other parts of the app, creating a win for the user, the developer, and the binary.



