Expert tips to speed up your iOS builds

Spend less time waiting and more time doing the work you love!

One of the defining moments of my software career was learning the motto “if it hurts, do it more.” What the heck? This concept feels totally counterintuitive. But give it a moment’s thought, and you soon realize that as developers we are instructed to lean into the bad parts of our process so that we fix them and make them stop hurting. 

The practice of continuous integration is a direct outcome of this approach to software development. Martin Fowler explains:

In a complex process, like software development, you have to frequently check where you are and make course corrections. To do this you must look for every opportunity to add feedback loops and increase the frequency with which you get feedback so you can adjust more quickly.

As iOS developers, the toolchain we use is radically different than other domains. Unlike most software, we don’t get to choose our editor or customize it much. Instead, it feels like Apple hands down Xcode, records a few WWDC videos and says “That’s all you get! Good luck!”

But don’t worry. There’s more to the Apple toolchain than meets the eye. In this article I will share several tactics you can use to shorten your iOS build time and speed up feedback loops.

In this post, I’ll show you how to:

  • Improve Swift hygiene for faster compilation
  • Profile, cache, and parallelize builds in Xcode CI
  • Maximize speed with the right hardware

If faster iOS builds are top of your wish list, you’re in the right place.

Compiling your app faster

Apply Swift hygiene

Swift is a powerful language with wonderful features like type inference, but it is important to understand how these language features add compile-time overhead and what you can do to help the compiler work faster.

Mark classes as final and favour value types

Non-final classes force the compiler to assume they might be subclassed, preventing certain optimizations. To avoid this, mark any class that isn’t intended for subclassing as final. Then use structs or enums where possible, since value types compile faster.

Add explicit type annotations

Swift’s type inference is convenient, but the compiler spends extra time figuring out types—especially in complex expressions or closures. To fix this, provide explicit types for variables, constants, and closures when the inferred type isn’t obvious. 

Here's an example:

// Before
class Frambulator {
    let dataDictionary = someFunctionThatReturnsDictionary()
}

// After
final class Frambulator {
    let dataDictionary: [String: Banana] = someFunctionThatReturnsDictionary()]
}

Profile and monitor builds

Even with idiomatic Swift, slow downs might lurk in your codebase. Xcode’s Build Profiler helps you spot the biggest bottlenecks.

Use Xcode’s Build Profiler

Enable build timing summary

  • In Xcode, go to Product ▶ Perform Action ▶ Build Timing Summary.
  • Xcode’s build logs will tell you how much time was spent on particular build tasks (ex. PhaseScriptExecution) so that you can identity and address outliers.

Interpret the build timeline

The build timeline visualizer, which is available via the Xcode Assistant view, displays a color-coded report, showing more granular task execution times like Swift compilation, linking, and asset compilation.

  • A healthy build profile shows many tasks running in parallel (each colored swim lane is busy).
  • Large blank gaps or a single long bar, like the one below, indicates a blocking task causing serialization.

Investigate slow tasks

  • Often you’ll find a single large Swift file or a module that dominates compile time, making it a prime candidate for optimization. In the example above, from the iOS Signal app, migrating from a giant if-else block to a switch eliminated the bottleneck.
  • Click on a long task to see which file or process is the culprit.

Configure CI alerts

If you don’t monitor build times, you might not notice when they creep upward. Setting up an alert can prompt you to investigate before slow builds spiral out of control.

How to set it up:

  1. Define an SLO (Service Level Objective), for example: “No build should exceed 10 minutes.
  2. In your CI system, configure an alert to trigger if the build time surpasses that 10 minute threshold. Bitrise supports this alert functionality via its Insights feature. Other CI tools may or may not have this capability.

Did you know?

Top performing teams on Bitrise complete PR pipelines in 10 minutes or less.

Speed up Swift macros with Xcode 26

Swift macros are a powerful language feature to avoid boilerplate, but the feature comes with a cost. If you use macros, you might have noticed that your build or test runs slowed down when macros were added. Prior to Xcode 26, SPM (Swift Package Manager) would fetch the entire swift-syntax source and compile that as a part of your app’s compilation process. Xcode 26 solved this issue, so update to 26 if you haven’t already! 

Upgrade your hardware for speed

Use the latest Apple silicon

Apple (and all chipmakers) are on an endless march toward faster and faster machines. Simply using the latest hardware can dramatically speed up your builds.

Apple's M4 Pro chips, the fastest option for Mac Minis to date, enable iOS developers to build and release apps faster and more efficiently than ever before. 

The M4 Pro vs M2 Pro and M1 Max: what’s the difference?

Apple manages to increase transistor count by about 25% compared to its predecessor for each new generation of Apple Silicon. Within the same generation, the Pro version usually has double the transistor count of the base version, and the Max has nearly double that. The chart below shows a comparison between our largest Macs from the past few years.

Putting M4 Pro to the test on Bitrise!

To see the impact of the M4 Pro chips firsthand, we tested the M4 Pro using the public Xcodebenchmark tool with the Xcode 16.2 Bitrise stack. It compiled the project 35% faster than the equivalent M2 Pro machine.

Read more about our results here and find out how to make the switch to M4 Pro machines if you’re already a Bitrise customer.

Optimize CI caching and testing

Run tests in parallel on simulator clones

  • Use xcodebuild’s parallel options
    Reduce wall-clock time for test execution by passing -parallel-testing-enabled YES -parallel-testing-worker-count <number> to xcodebuild so tests run in parallel across multiple simulator clones. This reduces the overall wall-clock time for test execution.

Fan out across CI runners

You can extend the parallel testing strategy even further by using it across several CI runners in parallel. This Bitrise blog post explains how to shard tests across multiple runners, further reducing wall-clock time.

Enable compilation caching

Take advantage of Xcode 26’s new feature, compilation caching. In Apple’s summation, “Compilation caching has been introduced as an opt-in feature, which speeds-up iterative build/test cycles for Swift and C-family languages.” We have seen build speed improvements as substantial as 30% with this new feature. Read more in our blog announcement.

Ensure fast, reliable local storage

Build systems—Xcode, Bazel, etc.—use a local cache (ex. DerivedData) to store intermediates for re-use. If disk space is too small, that means cache eviction, reducing the hit rate and extending build durations. We’ve observed this problem for Bazel teams in particular. To avoid this, opt for machines (or VMs) with sufficient SSD storage for the project requirements.

Also, ensure these files reside on the fastest local disk, not on network-mounted volumes (what AWS Mac EC2 instances use). For Macs used for CI, consider oversizing the SSD to account for the lower write cycles of this consumer grade hardware. To read more about considerations for your machines, read our blog post on the topic.

Your iOS build speed checklist

Here’s a quick recap of the top tips to speed up your iOS builds. Put them into action today to enjoy faster builds and more time for the work you love:

Swift hygiene
  • Break large functions into smaller ones.
  • Mark classes final when inheritance isn’t needed.
  • Add explicit type annotations to reduce compilation time.
Build profiling and monitoring
  • Use Xcode’s Build Timeline to spot blocking tasks.
  • Refactor or split large Swift files that dominate compile time.
  • Define a realistic SLO (e.g., build < 5 minutes).
  • Configure your CI to send alerts when that threshold is exceeded.
Swift macros
  • Use Xcode 26 to eliminate the old swift-syntax bottleneck.
Hardware
  • Opt for the fastest machines (maximize CPU P-core count).
  • Overprovision the SSD on your machines.
CI Caching and Parallel Testing
  • Turn on simulator clones (-parallel-testing-enabled YES).
  • Shard tests across multiple CI runners.
  • Use Xcode 26’s compilation caching feature.

Apple can sometimes make me feel like the kid at the bowling alley with bumper rails on his lane. Xcode is so neatly packaged compared to an editor like VSCode, where the power and the chaos is in the customization and plugin system. The same feeling applies to the build system, where xcodebuild is almost magical and hidden, while Gradle, the equivalent tool for Android, is so overwhelmingly flexible.

But it turns out there are still a bunch of ways that we iOS developers can tune our project. We have knobs we can turn for faster builds, less time watching the progress indicator, and quicker feedback loops overall.

Interested in more iOS dev tips and tricks? Read my eBook: Level up your iOS game here.

Get Started for free

Start building now, choose a plan later.

Sign Up

Get started for free

Start building now, choose a plan later.