Technical Decision-Making in a Fragmented Space: Spotify In-Car Case Study

July 10, 2024 Published by Maheen Khalid, Senior Engineer

Car rides have become connected and interactive these days with drivers jamming to music or catching up on podcasts or audiobooks while they’re on the road. A big portion of Spotify listening happens in the car — a key reason why it’s important for Spotify to ensure users have a smooth experience in the car, striking the perfect balance between safety, simplicity, and control. Achieving such balance is not easy due to various challenges: to maintain interoperability among different Spotify experiences, provide seamless usage on all kinds of screens, and manage drivers’ limited focus.

Interoperability among different experiences

There are three ways to play Spotify in your car:

  1. Using a Bluetooth connection: This method utilizes the car’s speakers as audio outputs. Users can execute basic playback operations such as play/pause, skip forward, and skip backward, using controls located on the car’s media head unit and steering wheel.
  2. Via a projected experience: Examples of this include Apple CarPlay and Android Auto, which project phone applications onto the car’s media unit. Through the projected Spotify app, users gain access to more-advanced functionalities such as browsing playlists, conducting searches, and utilizing a specialized Now Playing view, in addition to the basic playback controls mentioned above.
  3. With an embedded app: An increasing number of car manufacturers are integrating specialized operating systems into their vehicles’ hardware. These systems provide access to the car’s hardware and offer a dedicated media unit to the driver, featuring standalone media and navigation applications. Tesla and Android Automotive cars are prime examples of this integration.

It’s worth noting that most cars come equipped with Bluetooth capabilities, and on top of that, many modern vehicles offer projected and/or embedded experiences. This means that Spotify can provide users with multiple experiences within a single vehicle. Moreover, considering other surfaces where the app is utilized simultaneously (smart speakers, TVs, smartwatches, etc.), it is imperative that Spotify operates seamlessly across all platforms.

Dissimilar screen dimensions

Cars are equipped with screens of various sizes and dimensions, ranging from compact displays that barely show the track name to larger ones akin to a tablet. Adding to the complexity, there are many ways users interact with these screens. They might use physical buttons, rotary knobs, touch screens, buttons on the steering wheel, and even voice to manage music playback and adjust volume. On top of this, the car manufacturers also strive for fragmentation to better position their unique offerings, which makes tackling the automotive domain even harder for developers. Naturally, Spotify is expected to work seamlessly across all these different modalities for input. 

Limited focus from user

When it comes to selecting what to play in the car, it’s a bit different compared to other situations, where the user can devote their full attention. Safety and navigation take top priority for drivers, which adds a layer of complexity to the experience. The principles are as follows:

  1. Minimizing cognitive load: Since selecting and playing music isn’t typically the first thing on a driver’s mind, Spotify needs to step in to make it as easy as possible. The goal is to reduce the mental effort required, ensuring that choosing music is simple and doesn’t distract from the primary task of driving.
  2. Reducing distractions: Our goal is to keep drivers focused on the road at all times. That means minimizing anything that could pull their attention away, like unexpected interruptions in audio playback or confusion about what’s playing. These distractions can cause drivers to glance away from the road, which must be avoided. 

By addressing these challenges and ensuring that Spotify integrates seamlessly into the driving experience — without compromising safety — we can create a safer and more enjoyable audio experience for drivers.

Our approach for technical decision-making 

Given the assortment of challenges, the automotive domain is often seen as fragmented. Bringing together teams from different parts of the company is crucial to address these complexities, and effective modes of technical decision-making are paramount. 

Because of our distributed workforce, Slack serves as our primary tool for communication. However, it’s not always the platform most conducive to in-depth technical discussions, as conversations tend to get lost in various threads, and the level of detail may not suit all stakeholders. 

For technical decision-making, we prefer Request for Comments (RFC) documents. RFCs focus on a single problem, allow stakeholders to discuss that problem asynchronously, and refine the solution. You can find various templates for writing an RFC online, but the gist of it is that you start by describing a problem statement, give a little context around it, then move on to share your proposed solution for the problem along with some alternate solutions. When you’re ready, you can share the RFC document with stakeholders to get feedback on your suggested approach. 

Making the most out of RFCs

  1. Break down the problem (if applicable).

Technical problems come in all shapes and sizes. Some are small enough to conveniently fit one RFC, and others are hefty – the ones that cannot be squeezed into just one RFC. Addressing such issues with a single RFC can result in a long and complicated document, which is challenging to understand and can overwhelm the reader. 

When we encountered such large issues, we came up with a plan — to break down the problem into smaller, bite-size pieces. Therefore, we first presented a big-picture RFC. This gave all stakeholders a bird’s-eye view of the problem and framed potential high-level solutions, just to get the ball rolling. Once we had a decision on that, we started producing smaller, focused RFCs, each one diving deep into a specific issue, and shared these with the relevant teams.

For example: consider automatic playback when a car is connected. We expect that when a car is connected, Spotify should start playing music based on the user’s recent listening history. The bird’s-eye RFC on the topic contained high-level details like architectural design: Should this be a completely new system, or can we add this feature to an existing system? How would the API look? What content should be played? Etc. Once the architecture had been finalized, we moved on to more detailed RFCs covering topics such as the following:

  • Detecting a car connection signal
  • Determining the circumstances when automatic playback should not be triggered
  • Experimenting with different types of content to provide the best user experience
  • Filtering content considering that the user is in the car 

The audience for these RFCs varied based on the topic. For instance, content-related RFCs were shared only with content teams, while car-signal-related RFCs were shared with teams responsible for the connected accessories space. 

This approach makes problem-solving way less daunting, keeps tasks manageable, and prevents information overload, ensuring that each stakeholder team can focus on the aspects most relevant to them.

  1. Include diagrams and code snippets where feasible.

We often face the challenge of explaining significant changes in our systems, and clarity is crucial in these situations. So, what do we do? We rely on visuals — diagrams, code snippets, and even draft pull requests when necessary.

Diagrams can easily show how things are connected, how components depend on one another, and how work flows, making complex ideas easier to understand. Apart from using architectural diagrams in our RFCs, we also use diagrams to show user journeys, with the aim of highlighting shortcomings in our current systems.

As for code, it is our trusty go-to for showing standardized examples for implementing specific protocols or functionalities. It works best when suggesting changes to other teams’ systems. By keeping things consistent across different setups or platforms, we make sure everyone is on the same page.

Revisiting the example of automatic playback in the car, we created an RFC to highlight various situations where automatic playback could fail and proposed actions to prevent such failures. This RFC was intended for external teams that owned the systems we depended on. To clearly illustrate the problem areas, we used various user journey diagrams, providing a visual overview at a glance. Additionally, we included code examples to demonstrate the suggested improvements, making the technical solutions more concrete and actionable.

Using diagrams and code snippets throughout our RFCs provides readers with more context and details without unnecessary repetition, like giving readers a road map and a manual, all in one, making everything well-organized and easy to follow.

  1. Utilize RFCs for problem-solving and encouraging collaboration.

Sometimes we encounter issues that leave us even more puzzled. One such instance involved an issue with playback in the car that had been initially flagged as a bug. Turns out, it was a tricky one to reproduce in our usual testing setup, but as we dug deeper, it seemed like it could be part of a larger issue spanning multiple teams, with a more significant impact than we had initially anticipated.

To understand and map out the unknowns with the expertise of other related teams, we compiled everything that we knew into an RFC. We explained our part of the system and left sections for other affected or participating teams to fill out. This approach allowed us to present the problem comprehensively and provided a platform for all stakeholders to verify our findings, while also facilitating easier buy-in on proposed solutions.

Instead of patching the issue locally, the collaborative process helped us to consider all the perspectives and assess the potential impact before sorting through possible fixes and prioritizing what to tackle first. 

  1. Use RFCs to align between different functions.

One of the remarkable aspects of RFCs is that because of the way they are normally structured, they can bring people from different functions of a company together to tackle tough problems. It starts with defining the problem, diving into why the problem needs to be fixed, and finally, brainstorming ideas for how to solve it.

This method worked like a charm for us when we were deciding on new logging for a feature. We used RFCs to align between Product, Engineering, and Product Insights teams. Our product managers laid out what we needed and why, while the engineers and data scientists brainstormed ideas for how to make it happen.

For another example: implementing the support for features like AI DJ and Jam in cars. When implementing support for any external feature in the car, there are some key questions to ask, such as:

  • Does the current architecture support this new feature or does it need any enhancements? 
  • Does the car integration need more information than currently exposed by core API?
  • How will the logging work to determine that the listening is happening in a car? And so on. 

RFCs always provide a good way for the engineers, product managers, and data scientists from different verticals of the company to come together and find optimal solutions to such issues.

Conclusion

Navigating the integration of Spotify into the fragmented automotive ecosystem has posed its challenges, requiring intricate solutions. Throughout this journey, RFCs have proven to be a valuable tool for facilitating collaboration, iteration, and informed decision-making in the development and implementation of our systems.

While we’ve fine-tuned RFCs to align with our organizational needs over the years, it’s essential to recognize that every team is unique. What proved effective for us may not necessarily yield the same results for others. Therefore, we encourage teams to experiment and explore the full potential of RFCs within their own contexts.

By embracing flexibility and innovation, teams can discover new avenues for leveraging RFCs, ultimately enhancing their collaboration and decision-making processes.

Special thanks to Marko Tiidla and Robert Abramczyk for all the guidance and support during writing of this blog post.