Kotlin has taken hold of the Android development community at large: Google reports over 60% of professional Android developers write Kotlin code, and modern Android frameworks, such as Jetpack Compose, are written in Kotlin.
Instagram was the first out of Meta’s family of apps to embrace the shift to Kotlin. In this blog post we’ll share our Kotlin story: how we migrated a codebase of eight million lines of code (LOC) from Java to Kotlin, what the future of Kotlin development looks like at Meta, and learnings along the way.
At Google I/O in 2019, Google announced that Android development is Kotlin-first. Even before this announcement, the developer community at Instagram believed in Kotlin’s value and strongly advocated for Instagram to begin the shift to Kotlin. Such overwhelming support of the Android community begs the question: Why is Kotlin so popular?
Writing Android apps in Kotlin offers many benefits. The most important for Instagram were…
- Nullability. The primary source of crashes for Android apps on the Playstore is Null Pointer Exceptions (NPEs), and Instagram also feels this pain. NPEs historically accounted for over two-thirds of crashes on Instagram, although with Kotlin adoption this number has gradually diminished over time. Spending time fixing bugs takes Instagram developers away from doing what they love most: iterating on exciting products and features. The promise of solving our biggest source of bugs on Android made adopting Kotlin at Instagram a no-brainer.
- Developer experience (DevEx). Kotlin syntax significantly reduces boilerplate, embraces functional programming, and offers robust APIs to enable developers to increase their productivity. Kotlin offers inline functions, final classes by default, and explicitly declared, immutable data.
- Less code. When you maintain an app with billions of LOC, conciseness is key. Jetbrains estimates that Java code, migrated to Kotlin, results in 40% fewer LOC on average.
- Declarative UI. Instagram is actively moving away from writing UI code with extensible markup language (XML) and embracing Declarative UI instead. Jetpack Compose is built around Kotlin and enables developers to write good Compose code. Declarative UI is a stepwise improvement to developer productivity and enables developers to ship beautiful UI.
Timeline of Adoption
As the Android community at large shifted more and more to Kotlin, it only made sense that Instagram would begin exploring Kotlin officially in 2019. That year, we focused on experimentation. We validated that Kotlin code did not change user engagement metrics or elevate bugs with split (A/B) testing. Our Developer Infra team partnered with one product team to write a single surface in Kotlin. Meta-wide DevEx teams integrated Kotlin support into our build chain.
By January of 2020, Instagram had 7,000 lines of Kotlin code. Our work in 2019 had laid the foundation for a Kotlin opt-in phase in 2020. Product teams wishing to adopt Kotlin identified a Kotlin point-of-contact (POC) who was in charge of establishing the team culture for Kotlin code reviews and alerting Dev Infra teams of any uncovered issues. Dev Infra built Kotlin Lint support and improved the Kotlin integrated development experience (IDE). Seventeen Instagram teams signed up for the opt-in phase, and by the end of 2020 Instagram had 160,000 lines of Kotlin code.
In the first half of 2021, Instagram reached an important milestone: Kotlin reached open adoption. This meant that any engineer could commit Kotlin code to the codebase. At this time, all teams were encouraged to learn Kotlin, and Dev Infra teams provided Kotlin support channels and best practices. We also achieved full IDE support parity between Java and Kotlin.
By August of 2021, Instagram had become “Kotlin-first.” This reflected a culture shift from open adoption: It was now an expectation that all newly committed Android code would be Kotlin. Kotlin adoption at Instagram had reached approximately 30% LOC, and Instagram teams were reporting that Kotlin was improving their developer experience and enabling them to ship features quickly. This all occurred ahead of Kotlin adoption by the rest of the company: Facebook first reached 100,000 lines of Kotlin code at the end of 2021.
Kotlin-first… but build speeds?
As exciting as Instagram’s Kotlin-adoption story was at that time, we could not ignore one major problem: As the rate of Kotlin adoption increased, build speeds for Instagram Android engineers regressed significantly. At the end of 2021, Instagram Android build speed had decreased by 100%, so we opened an internal SEV.
Why such a dramatic increase in build time? We found a few reasons:
- Compiler maturity. Java was first released in 1996, while Kotlin 1.0 was released in 2016. The Java compiler is much more mature than the Kotlin compiler and has 20 years of efficiency optimizations over Kotlin.
- Build system support. At Meta, we use a build system called Buck that we built internally and later released as open source. Java support has been heavily optimized and iterated on for years, and Kotlin support was recently shipped in 2019.
- Language sugar. Although both Java and Kotlin are compiled down to Java virtual machine (JVM) bytecode, Kotlin has many language features that Java does not. These features incur compiler cost, and the price is paid in additional build time.
Instagram might have turned out to be the only app with a significant Kotlin footprint, but the DevEx value was undeniable and Meta understood that it was a matter of time before the rest of the Family of Apps followed. Facing a growing build-speed problem at Instagram, Meta invested in creating a build-optimization tool called Kosabi.
Kosabi is a set of compiler plugins that work together to generate source-only ABIs for Kotlin Buck targets. When building a Buck rule, Buck creates an ABI (Application Binary Interface) JAR (Java Archive) that is alongside a library JAR. The ABI JAR contains all of the public information about the compiled code, acting as the public interface for the target. The source JAR contains everything, including private method bodies. Using ABI JARs instead of library JARs on the compiler’s classpath can boost performance because the compiler can load the smaller ABI JAR much faster than the source JAR.
ABI JARs can be built in different ways. A class-only ABI JAR builds the entire JAR first and then removes all private or non-public information. A source-only ABI JAR looks at the source code and makes inferences to ascertain information that usually can be determined only by looking at that JAR’s dependencies. Using source-only ABI JARs improves compilation speed by allowing for dramatically more parallelism and reduces the number of cache fetches when compared to class-only ABI JARs.
In the visual below, you can see a build graph of source-only ABI JARs on the left and a build graph of class-only ABI JARs on the right. Using source-only ABI JARs allows for more parallelizable paths in the graph: You can see that the depth of the graph is shorter, and there are a greater number of paths from the root. With source-only ABI, more JARs could be compiled in parallel, while with class-ABI JARs, more execution was sequential.
In 2022, Instagram piloted Kosabi. By the end of 2022, Kosabi had been integrated into 87% of the codebase, and Kotlin build speeds had been reduced by 55%. This allowed us to stabilize build speeds despite the fact that Kotlin kept growing in the codebase. By the end of 2022, Kotlin had reached 40% LOC in Instagram, yet build speeds did not change significantly.
In 2023, we passed an exciting milestone at Instagram: More than 50% of our codebase is written in Kotlin. As we continue to look to the future, the next major milestone for Instagram is to transition from “Kotlin First” to “Kotlin Everywhere.” To make this happen, we’ve invested in infrastructure such as automated Kotlin conversions, where a script migrates Java files to Kotlin and submits a pull request.
As Kotlin continues to grow in the Instagram codebase, build speeds remain top of mind. Kosabi has significantly improved Kotlin build speeds, but we still have work to do. Jetbrains’ new Kotlin compiler, K2, is benchmarking a 55% improvement in compiler-throughput speed. K2 is a complete compiler rewrite and will require a full rewrite of all Meta compiler plugins, which in a codebase this large is no small feat. As we look to the future, improving our compile-time infrastructure to adopt the new K2 APIs will result in build-speed wins and higher fidelity in our build infrastructure..
Leading the charge again, Instagram is piloting K2 in the codebase on developer builds in the second half of 2023. We’re committed to a future where the Instagram Android codebase is written in 100% Kotlin and we’re excited to continue the journey!