Yesterday, the Life360 servers handled 2,167,980,001 API requests from our iOS and Android mobile apps. That's the most requests we've ever served in a single day, representing the most users we've ever had in a single day.
Having millions of monthly active users worldwide is an awesome accomplishment. Of course it also comes with challenges–the challenges of Scale. Our Platform and Infrastructure engineers are having a blast developing the technology to handle over 2 billion daily API requests; but why should they have all the fun?
On the Mobile Engineering team at Life360, we deal with an entirely different set of challenges. Among the challenges we face on the mobile side are:
- Battery usage: When an always-on location app uses too much of our users' precious watts, they simply uninstall it. How can we maintain fresh GPS streams, while being conscious of our power consumption?
- Cellular data usage: Our users, especially those in families, are very conscious of their apps' data usage. We must take this into consideration when providing location streams, or adding in new SDKs.
- Live data: Now more than ever, people expect their apps to have the proper data right when they open it. Loading screens are so 2017—live data is the future.
- Upgrading core technologies: Occasionally we want to adopt some new technology in our codebase. How can we make this upgrade quickly, while still providing a bug-free quality experience for our users?
In this post, I will focus on the last two challenges in this list: How do our apps provide a "live" experience, and how is our codebase built to allow for easy upgrades of underlying technologies?
This post is the first in our series on Mobile Data at Scale. Stay tuned for more as we address the challenges we face with a large and growing mobile userbase.
The Bicameral Codebase
Providing a live data experience in our iOS and Android apps is a question of architecture. We have separated our codebase into two parts: the user interface layer, and the data layer that supports the UI. This allows us to build fluid user interfaces without being concerned with the data that supports them.
The data layer abstracts all of the networking and persistence functions of our app. We have further abstracted all the networking and persistence code into a Model Store.
The Model Store
The Model Store is the data engine for our application. It is the singular machine that maintains and provides data for use in our UI. A Model Store has five capabilities:
- Updating data from the network
- Persisting this data to the local disk
- Allowing for fetching and querying of this cached data
- Allowing for mutation and updating of this data
- Providing change notifications to consumers when this data changes
Introducing a Model Store with these capabilities allows us to maintain an entirely bicameral codebase. That is, our codebase is separated into two decoupled parts. "Above the line", we have the UI code which consumes streams of data entities from the Model Store. "Below the line", our Model Store takes care of all of the networking and persistence necessary to have the right data at all times.
Within the Model Store, we can solve problems like caching, network retries, and storage optimization. Within the UI portion of our code, decoupled from the data, we can focus on animations, accessibility, and fluid user experiences.
Benefits of the Model Store
Faster feature development
With the networking and persistence functionality of our application neatly nestled within the new Model Store engine, feature development is much simpler. Now UI engineers do not need to concern themselves with how their data is stored, where it comes, or where it goes. They simply subscribe to streams from the Model Store. This reduces the time to market for high-quality, data-rich features.
I asked a couple of my colleagues on the iOS and Android teams how much time they spend writing networking and persistence code during feature development. I found that we roughly spend 30% of our feature engineering time writing code that deals in some way with networking or persistence. This was prior to the introduction of the Model Store.
I conducted my informal poll after we built the Model Store, and found staggeringly awesome results: now only 10% of our feature engineering time is spent writing networking and persistence code.
The average feature once took us two sprints, or 20 working days, to develop. Now it takes 16 days. That's a 20% productivity improvement. Admittedly, these results are far from scientific. However, I can say with confidence that we are now benefiting from faster feature development time.
With the Model Store in place, we are able to focus on other aspects of development, such as providing high-quality animations and interactions for our users.
Smooth technology upgrades
Now that our codebase is bicameral, the UI code is entirely decoupled from our database and networking technologies. This allows us to more easily swap out these technologies. For example, in moving from Core Data to Realm for data storage in our iOS app. This is now much easier for us because the UI code wouldn't have to change at all to support a new database.
Improved Software Design
The Model Store is being designed and developed together by both the iOS and Android teams at Life360. This represents an unprecedented level of collaboration between the two teams, as we can now solve the same challenges together. We have essentially doubled our team's software design capacity by maintaining a shared architecture and design for the Model Store. There are many challenges and benefits of this unified design process. This topic deserves its own post, so I won't go into it here.
Given that we will have a clear delineation between UI code and networking & persistence code, it becomes more natural for our developers to specialize in particular areas of the codebase. The tools are in place for us to bring on passionate interaction engineers, or killer networking specialists, and they can focus on what they do best. The Model Store was an upgrade for our team.
The Model Store Future
With an improved architecture in our mobile applications, we are in a much stronger position to think about the future of our codebase. Moving from HTTP/REST to MQTT for more of our network communications, for example, becomes a much more tractable problem.
If any of these challenges or technologies interests you, we'd love to chat. Check out our open positions and get in touch with us.
Special thanks to the organizers of AnDevCon 2017 for inviting my esteemed colleague, Orrin Cross, to speak about the Model Store, as well as to the organizers of 360 iDev 2017 for allowing me to speak on the topic. We will provide links to the talks as they become available.
Keep an eye on the Life360 Engineering blog as we continue to write more about the Model Store and Mobile Data at Scale. There are plenty of fascinating topics we'll explore, including RxSwift / RxJava, and VIPER / RIBlets architectural patterns. See you next time!