Skip to main content

 

Introduction

Duolingo is the world’s most popular language-learning app, with over ten million daily learners, because they’ve managed to make something people found daunting feel easy and fun. This continued success relies on a constant stream of innovations and updates — and a smooth-running app that can deliver all of them. To Duolingo, a single unresponsive app in a device anywhere in the world could mean a learner potentially discouraged. This commits them to app excellence, particularly on the Android devices used by sixty percent of their learners, including their CEO, who keeps track of the app from an entry-level phone. And so, when Duolingo's Android development team registered an increase in “App not Responding” errors, dropped frames — and even received a hand-written complaint — they took action immediately.

Their situation wasn’t that uncommon. Apps that lack scalable architecture and clear best practices often perform well at the beginning but show signs of technical debt as they grow. Duolingo’s Android codebase was designed to allow them to add and release new features rapidly, but the lack of an agreed-upon architecture was manifesting in increasingly frequent performance regressions. It was starting to suffer from unreliable frame rates, visually inconsistent or broken interactions, and a growing assortment of new bugs. These regressions not only inconvenienced learners but also cost the team substantial development effort to diagnose and repair. Duolingo’s Android development team realized that if they wanted to keep shipping new features while providing the target level of user experience, a new approach to their codebase was needed.

Discovery

First, they had to get to the bottom of what exactly was going on. A deep dive into the numbers uncovered that, as they added new functionality, the app’s rendering performance was regressing 5-10% every month. In fact, one particularly unwieldy release had increased crashes by 10%, slowed frame renders by 25%, and saw lessons starting 70% slower on entry-level devices.

Further analysis of their code led them to the conclusion that most of the app’s issues could be traced back to a single bottleneck: a global state object called DuoState, which was responsible for maintaining state across different features of the app. A number of popular features (like experience points and daily streak tracking) were using it to access vital information. Centralizing their data in this way had once enabled the team to iterate rapidly. They simply added properties to DuoState whenever a new feature needed to share information across the app. But now the unoptimized and frequent access to the object was causing increasing performance regressions.

DuoState was so tightly coupled to the entire codebase that even small changes could impact the rest of the app. The team feared that a minor new feature could have the unforeseen side effect of triggering many internal updates to the app, causing the entire release to be too slow for many devices. These performance regressions became more frequent as the app grew, and the team onboarded new engineers to keep up with the accelerating product roadmap. In 2020, as they added more developers, they were starting to see significant regressions cropping up as often as every 90 days. Upon closer inspection, the likelihood of a regression in a given release was proportional to the number of changes it implemented. At this rate, these regressions would completely derail the product roadmap within a few years.

This outdated architecture had become a bottleneck for both the performance of the app and the velocity of the team. After much internal debate, they stopped development of new features, including some closely tied to their bottom line. For two full months, Duolingo’s development team went all-in on refactoring their Android app in an effort they called the “Android Reboot”.

The Android Reboot

One of the team’s first key takeaways was that their code lacked clear boundaries. The DuoState object was readily available at any point in the code, inviting developers to access it frequently in inefficient ways. They needed to create a greater separation of concerns within the codebase. They decided to tease apart each feature into its own, clearly-defined module, using the Model-View-ViewModel architectural pattern. MVVM allowed them to remove calls to the monolithic DuoState object, letting many modules work in separate threads.

Diagram showing before and after implementing the Model-View-ViewModel architectural pattern

The team’s familiarity with MVVM, and Google’s support for it, made it an obvious choice. It allowed them to clearly document what logic should go into what files (including views, view models and repositories). This helped make their feature architecture more consistent. With a clear path to follow, the team quickly began refactoring their monolithic code into sets of classes with clear boundaries and responsibilities.

Along with MVVM, the team used Dagger and Hilt (also included in Android Jetpack) to implement repository patterns to replace DuoState. Dagger generates clear readable code that provides verbose error logging designed to help developers understand exactly what their code is doing, eliminating dead stack traces to reflected properties; and Hilt reduces the amount of boilerplate code needed to write for this.

This new architecture allowed the team to split DuoState into smaller objects. This immediately reduced unnecessary coupling between domains. For example, the code responsible for tracking a user’s progress could now access their experience points but not the number of times they’ve logged in during a month. These new architecture guidelines meant that while no single thing was too difficult to change, it took coordination and planning to change it across the app. Implementing the new architecture across the code base drove significant performance gains in aggregate.

MVVM architecture facilitates a separation of concerns between the domain data, the interface the learners see, and the logic for how these two realms interact. It gave Duolingo’s developers a more deliberate way to control how the app responds to internal state updates. They could now develop more complex user experiences without the risk of triggering regressions, or affecting the underlying business rules.

Developer Productivity

In the past, inconsistent application of development patterns made different parts of the codebase harder to understand and maintain. Without consensus, each developer implemented code as they saw fit.

MVVM, Dagger, and Hilt, provided the team with a more detailed understanding of how new features should be implemented. Following these best practices made the code easier and more predictable. Developers could now assist in debugging features that they hadn’t originally worked on. And new developers could be onboarded more efficiently; as long as they understood the architecture, they could contribute meaningfully right away. This new clarity significantly boosted the team’s development velocity.

Ensuring Quality

Crucially, the new architecture also revealed that certain animation features in the app were underperforming on entry-level devices. Accordingly, the other core focus of the Android Reboot was the reduction of jank, dropped frames, and "App Not Responding” (ANR) errors. The team used repository patterns to help streamline the sharing of data between threads. These patterns ensured that they could more efficiently use device resources with multiple threaded modules. Moving work off the main thread improved responsiveness, overall frame rate, and led to smoother animations on entry-level devices. Performance on flagship devices improved as well.

A Better Overall Android Experience

In the six months working with the new architecture, Duolingo’s Android team has continued to ship new features without recording significant performance regressions. The days where they had to halt feature production to hunt and fix bugs are safely behind them.

The app’s daily ANR rate dropped 41%. The percentage of time that the app’s frame rate fell below target decreased by 28%. And importantly, users experienced a 40% increase in speed when scrolling through lessons, the leaderboard, and stories in the app.

The reboot allowed Duolingo to consistently provide their trademark fun, effective, and delightful language learning experience on a much wider range of Android devices.

Conclusion

Duolingo’s dedication to their mission made them the world's top app in the language learning space. Their commitment to app excellence — creating cutting edge educational experiences without compromising accessibility — is what kept them there.

If you’re interested in getting your team on board for your own Android Reboot, check out our condensed case study for product owners and executives linked here.

Posted by Tom Grinsted, Scott Lin, and Tat Yang Koh, Product Managers at Google Play


Illustration of person holding phone looking at 4 star rating

Ratings and reviews are important. They provide valuable quantitative and qualitative feedback on your users’ reported experience of your app or game, and the broader service that you offer. That’s why they’re one of the signals people use when deciding what to download on Google Play.

We’ve heard from both Play Store users and developers that ratings and reviews could be more helpful. This is especially true when ratings from one area unfairly impact another — like when a bug that only impacted a single country negatively affects the app’s rating everywhere; or when positive improvements in a tablet experience are overlooked because of the number of users on phones. So we’re starting a multi-quarter program of improvements to make ratings more personalized and indicative of the experience each individual user can expect, and to make them easier to navigate and use for developers:

  • From November 2021, users on phones will start to see ratings specific to their registered country
  • Early in 2022 users on other form-factors such as tablets, Chromebooks, and wearables will start to see ratings specific to the device that they’re on

We understand that many developers closely monitor the ratings that their potential users see, so we’re making sure you have plenty of notice about these upcoming changes. We’ve also made enhancements to Play Console to help you understand your ratings and reviews - especially across form-factors.

Changes to Google Play Console

Device type insights

Expanding your support for different device types is one of the most important and impactful changes you can make to your user interfaces. Adding tablet-optimized layouts or better mouse and keyboard support for Chrome OS can result in a step-change in the quality of your users’ experience, which in turn influences their ratings and reviews.

New Device type ratings insights are available in Play Console 
ratings overview and breakdown pages

New Device type ratings insights are available in Play Console ratings overview and breakdown pages

To make it easier to spot opportunities across various device types and track the impact of enhanced experiences, we’ve added new Device Type dimensions to the ratings page. We’ve also added a Device Type filter to your reviews so you can easily see how your tablet users are rating you, or what your users on Chrome OS say in their reviews.

More flexible date and period selections

Many of you have told us that you want to access more granular data than our selectors allowed. So, we’ve broken down your segmentation options and made them easier to use. You can now independently select the time period you want to plot (from the last 28 days through to your app’s complete lifetime), and how you want your ratings data to be aggregated (daily, weekly, or every 28 days). This allows you to access more granular data over longer periods of time.

Select any time range and aggregation period independently 
to find the ratings data you want

Select any time range and aggregation period independently to find the ratings data you want

Download data easily

We’ve also enabled CSV downloads of your average data and rating distributions. Combined with the new data selection options, you can easily query and download much more of your data and perform offline analysis. For example, you could download your entire history of daily ratings distributions and correlate it in a spreadsheet with customer service contacts.

Access and download all your data including ratings breakdowns 
directly from the overview page

Access and download all your data including ratings breakdowns directly from the overview page

All of these changes are live in Play Console now. Visit Ratings analysis and Reviews to try them out.*

Upcoming changes to ratings in Google Play

Ratings help people decide which apps to download and they are taken into consideration for featuring and placement on Play Store. But because the app experience can vary depending on the user’s region and device type, aggregate ratings don’t always tell the whole story. That’s why, starting in November 2021, we’re going to change the ratings that individual users see based on where they’re registered, and later in the year what device they’re using.

From November, this means that users on phones will see specific ratings for the country or region they’re based in. So a user in Japan will see app ratings generated from those submitted by other Japanese users.

Early next year we’ll further update ratings to reflect the device type users are browsing Play on, whether it’s: tablets and foldable, Chrome OS, Wear, or Auto. This will give users a better impression of the experience that they can expect for the device they’re using. We recommend you take a look at your form-factor ratings today - especially for tablets where growth is very strong - to see if you should invest in optimizing your users’ experiences.

We understand that as a developer you will want to make sure you understand and get ahead of any major shifts in your user-visible ratings. So at least 10 weeks before any change in Play Store, we’ll automatically analyze the change your app can expect to see and reach out to any developer that will see a change of more than 0.2 stars on any device type in a key market (one with >5% of your store listing visitors). This will give you time to plan if you want to make key changes to your app.

These changes in Google Play will start to roll out from November with country or region-specific ratings. Look out for messages about your ratings in your Play Console Inbox towards the end of this year, and don’t forget that you can get ahead by checking your ratings by country and device type today.

Comments