How we reduced Pinterest’s iOS app size by 30+% / 50MB

Pinterest Engineering
Pinterest Engineering Blog
3 min readApr 16, 2021

Liang Ma | Software Engineer, App Foundations

We all know app size (download size[1] and local install size[2]) matters, and there is a correlation between app size and customer engagement. Many times, people make decisions about using software based on size, and even pay for bandwidth by the megabyte. Not to mention, uninstall rates could go up when app size increases and causes users to try to free up disk spaces on their devices.

Recently, we shipped an improvement in the Pinterest iOS app v9.1, which significantly reduced its size:

Table 1: iPhone 11 Pro is our target device.

As a result, we’re seeing increased app installs (users download apps from the app store) on new versions since the rollout.

What’s the issue

For context, at Pinterest, we use Bazel for our iOS builds. If you’re not familiar with Bazel, this article is worth a read.

To create our localization files, we have a CI job that auto-scans all source code in the app (via bazel query) and sends them to Mojito for translation. This worked well until we added several extensions.

Each extension is a module with its own BUILD file. After Bazel was built, it would copy the localized strings from the main app bundle to each extension bundle. However, this would make copies of the Localizable.strings file in each extension, thus inflating the overall app bundle size.

So we decided to eliminate localization copies from extensions.

The fix

First, we updated the BUILD file so extensions no longer copy localized strings from the main app bundle.

With this change, however, NSLocalizedString can’t properly load the localized string. After further investigation, we learned that these macros both use +[NSBundle mainBundle], but +[NSBundle mainBundle] actually returns the bundle containing the “current application executable”, which is a subfolder of your app when called from within an extension. For example: it is `/path/to/Pinterest.app/PlugIns/SiriExtension.appex/` instead of `/path/to/Pinterest.app/`. We made a change to set the desired path so NSLocalizedStringWithDefaultValue can read the localized strings from the main app bundle.

All of these changes saved — (size of all Localizable.strings) * (count of extensions that have such localizations duplication) — represents about 30% of the total app size.

Long term plan

As a follow-up, we plan to put localization resources into their respective SDK/extension, instead of relying on the app bundle, with the following advantages:

  • Each bundle will be self-contained so it doesn’t require the main app bundle to be able to run or test localizations, and it could be bundled into a separate app.
  • NSLocalizedString and localization APIs work naturally in the extension’s code.
  • We could make the bundles open source.

There are also other potential areas of improvement, such as removing unnecessary localizations for non-consumer-facing code, investigating more size-efficient image format(s), and other compiler level optimizations. Stay tuned for more updates, and visit our careers page if you’re interested in opportunities like this.

[1] Download Size is the actual size transferred when download from the app store, which will only be displayed if an app is over the Apple determined limit of 200 MB and the user is not on Wi-Fi unless users change the default setting. And it’s compressed, so it’s smaller than the usual Install Size.

[2] Local Install Size is the actual app size (Settings app->iPhone Storage->Pinterest->App Size) on your phone’s disk. It’s thinned for your phone model, so usually smaller than the Universal size.

--

--