Reinventing and Revolutionizing Fitness at Home

Peloton delivers high-energy workouts with real-time interactivity and motivation, live-streamed and on-demand.
Reinventing and Revolutionizing Fitness at Home
Peloton is a global fitness technology company dubbed by Men's Health as "the best cardio machine on the planet." The Peloton Bike and Tread deliver an immersive and convenient fitness experience, with live-streamed and on-demand classes and real-time metrics and encouragement via their Peloton Digital Membership. This article was written by Douglas Crossley and Chris Mohr of Peloton, originally published on the Peloton Engineering blog.
As our user base at Peloton continues to grow, we’ve found some interesting opportunities to connect members to each other. We think that creating more opportunities for shared, real-time workout experiences is an important initiative and something we wanted to invest in.

Using Real-time Messaging at Peloton

As our user base at Peloton continues to grow, we’ve found some interesting opportunities to connect members to each other. We think that creating more opportunities for shared, real-time workout experiences is an important initiative and something we wanted to invest in. The first large feature based around this goal was something we called Working Out Now, which involved letting members know in real time that another member they follow on our platform is currently working out. To support this, we wanted a mechanism that could easily notify members anywhere in the product. We wanted it to be minimally invasive while still providing detailed information when needed. Peloton Real-time Working Out Now

Real-time Messaging Integration

We were already using PubNub to send real-time updates in our user activity feed, which shows members their friends’ activity. We decided to continue using PubNub for our real-time messaging and simply expand on what we had in place.

For each member, we create a PubNub channel that their device subscribes to upon login. Whenever we need to send a real-time update to that member, we publish a message on that member’s channel. Each message has a type which we use to identify the schema of the payload. This allows us to easily create and consume new messages types.

On the client side, we encapsulate the ability to connect to PubNub and receive messages in our Messaging Service, which can easily be injected throughout the app for use. This Service exposes an Rx observable that supports filtering the message stream by type. This gives clients a simple way to only get messages they care about and know how to consume.

Know When Your Friends Are Working Out

In order to know which of a member’s friends are currently working out, we need to know every time one of those members joins or leaves a workout. We defined two types of messages: “Someone you follow joined a workout” and “Someone you follow left a workout”. Whenever a member joins or leaves a workout, the Peloton API publishes a message to the PubNub channel of each of the member’s followers.

After defining these message, we hooked up the client to receive them in our bottom navigation component. We decided to build a cache that would update every time we received one of these messages from the server and then request additional information as needed. This worked well while a member was on their Bike or Tread, but we still needed a way to know who was in a workout when the member first started their session.

Peloton Real-time Architecture Messaging Data Flow

We created a new API endpoint that allowed us to retrieve all the data for a member’s followers that we could leverage when our cache was stale or needed to be initialized. There was also a risk that the client’s local list of friends who were working out got out of date for a number of reasons. Instead of the client incrementally updating their local list, they request the full list of friends in classes each time they receive a message. Once the client has this information we use it to render our Working Out Now dialog that members see when clicking on a notification.

Conclusion

As we added more types of messages that were used by different parts of the app, it became more important to document the schema of these messages. We use an OpenAPI specification to document the schema of our REST API and applied this same pattern to real-time messages by treating them like endpoints. This allowed all client teams to easily consume any new messages that were added and understand how they could be used.

After allowing members to see which classes their friends were in, we built on top of this by allowing them to see their friends while they were in any class, including On Demand classes. We were then able to work with our Leaderboard team to provide an experience that better connected members to friends in class as well. This real-time messaging infrastructure gives us a base to expand upon for new features in the future.