Frontend at Lyft: An Overview

Fernando Augusto López Plascencia
Lyft Engineering
Published in
8 min readMar 9, 2021

--

At Lyft we have the enormous privilege of working with a product that impacts millions of people all around the US and Canada. Most people are familiar with Lyft through our apps, which are the main way our users give and request rides, rent a vehicle or take rides on bikes and scooters. There’s also the infrastructure that allows that to happen, mainly in the form of thousands of backend microservices. But did you know that there is a sizable portion of web frontend development as well?

While it might come as a surprise, frontend development is an integral part of what makes Lyft possible. Most of our frontend microservices are built on a Typescript-heavy stack; these services, for example:

  • Power lyft.com and affiliate websites,
  • Provide services to our corporate partners, allowing them to manage their fleets through the Lyft Network (such as our partnership with Hertz, which allows you to rent a car to drive with Lyft),
  • Allow the management of internal resources through easy-to-use interfaces that add reliability to our operations,
  • Empower our scientists to understand and improve how Lyft runs through data tooling,
  • Show dashboards through custom UX / UI to support activities such as indicator monitoring, searches and decision making.

All of the above need to be delivered with a high degree of quality. Frontend software development is a complex solution space, where a number of factors have to be taken into consideration, such as scalability, resiliency, consistent user experiences, heterogeneous client capabilities, realtime experiences, with code that runs on both server and browser environments. Accomplishing these goals will provide our riders and drivers with the best transportation experiences.

Tooling and infrastructure

To make things happen reliably, quickly, and at the same time provide an awesome developer experience, we invested in infrastructure tooling early on.

When I joined Lyft, in mid-2016, we were no more than 25 frontend engineers. Our frontend infrastructure was simpler, too, but it was already evident that the infra needed to become more scalable. Thus, we started migrating from an Angular-based monolithic approach for all frontend internal tools to a truly distributed network of React-on-Node services to host those tools.

Before: a frontend monolith connected to many backend services.

The transition from having dozens to hundreds of microservices was made possible by the use of shared, centralized libraries, such as our build system package, called Frontend Build. This allowed us to create a new service from scratch on top of Express, with preconfigured defaults for Webpack, and connected to the Lyft microservice mesh through Envoy. This also helped us better support recommended technologies and standards, such as Redux for state management and Jest for testing.

After: While the ratio is not necessarily 1:1, frontend services today are much more distributed.

Another shared piece of code, in this case for styling, were a set of classes that followed the atomic css philosophy, allowing everyone to create “Lyft-looking” interfaces by composing a set of well documented classes.

By this time, an internal portal to share React components was also created, using lerna and storybook. Each component becomes its own package in an internal namespace, which means each component is trivially easy to include in other frontend projects across Lyft.

Frontend Build kept evolving as the frontend environment did. For example, when the time was right, we stopped endorsing Redux as a default, in favor of a React Context-heavy approach. Still, developers and teams truly owned the ever-increasing number of services they created. This meant we were able to provide the best experience for each particular case, whether it was about data exploration, data visualization, or support resolution for our drivers and passengers through specific flows.

An excessively simplified view of how the frontend platform at Lyft has evolved.

Just four years later we’re almost a hundred frontend developers, distributed in six offices across two continents. The distributed approach was right for Lyft, but has also introduced some challenges. For example, having teams working independently on their own services meant that each service could diverge greatly from others. Due to this, we were at a point where upgrading Frontend Build was a complex task and, in some cases, a real showstopper — and not doing it could expose us to a number of issues, including potential security risks. It was time for a change, one that would still support a wide variety of use cases, streamlining upgrades, yet not leaving the developer out of the driver’s seat.

The solution came in 2020 with @lyft/service, a new infrastructure platform based on Next.js. Adopting Next.js means the infrastructure is, in many cases, automatically upgraded, but the developers and teams still get to retain control on configuration: most Lyft-specific integrations have migrated to a plugin system, and external packages are still supported. (For more on how this migration happened, read “Changing Lanes: How Lyft is Migrating 100+ Frontend Microservices to Next.js”)

In the meantime, our friends in the Design org, who were facing similar challenges, created the Lyft Product Language (LPL) design system, which now brings visual consistency to all our external mobile and web apps. Paired with this, in 2019 the first version of the LPL was created for frontend as a library called CoreUI. This has now replaced our old, atomic css classes. Being a port, CoreUI makes the implementation of interfaces much easier, since it’s based in the same language in which the designs were made. Also, CoreUI uses styled components for embedding CSS, which provides for much better modularity and smaller bundle sizes. Examples of what can be found in CoreUI are: typography, colors, inputs, buttons, dropdowns, icons, and layout components.

CoreUI is also hosted internally using Storyboard.

Today, almost a hundred different frontend-specific microservices exist in the Lyft ecosystem, owned by a variety of teams.

Organization and communication

Engineering at Lyft is vertically integrated. Instead of having teams organized by work function (e. g. a Frontend team, a Backend team…), every team instead owns a portion of the Lyft product.

For example, my team is called Pricing: we make ourselves responsible for providing accurate pricing for all rides, and the algorithms around that. This is a multidisciplinary effort, of which I, as a frontend developer, am also a part.

With this organization, a challenge is to effectively be in touch with other frontend developers. Collaboration needs to happen just to make things work: for example, every pull request has to be reviewed by another frontend developer. In my case, as the sole frontend developer in my team, I require to build relationships across teams just to make my work happen.

Frontend members are distributed across a number of teams.

This is why, as a distributed organization, Frontend at Lyft puts special emphasis on community and communication. Here are just some of the ways we achieve this:

  • We have a number of org-wide events, such as a monthly All-Hands meeting, where everybody — from the most senior members to the most junior ones — are encouraged to talk about what they care about.
  • We have a shared calendar where everybody that does frontend can check out what events are happening.
  • There’s a #frontend Slack channel for general questions, plus a number of specialized channels for inquiries about particular topics. Slack is a great way to get help fast, request peer reviews, look at tech issues others have encountered in the past, and so on.
  • We hold informal events as well, such as a monthly meetup called “Frontend and Friends,” with the sole purpose of connecting with each other.
  • The frontend organization also started its own mentoring program, which greatly helped reduce siloing and allowed individuals to support each other technically and professionally. This program has recently grown to include all of Engineering.
  • An internal portal exists to document all of the generally accepted frontend standards at Lyft. Another one lists all of the frontend services and how they align with these standards.

At the center of it all is our Frontend Working Group, a voluntarily-run organism that coordinates work to standardize and advance our technologies and internal standards, to advocate for the career and growth of frontend engineers, and to ensure we have a real community — a particularly tough challenge during the COVID pandemic.

The Frontend Working Group has executive sponsors and representatives from across all of Lyft’s business lines. It consists of a central group and three grouplets (Tech, Career and Community), with each grouplet working independently on a number of work streams. The Tech grouplet works on topics such as accessibility, state management, performance, etc. The Career grouplet concerns itself with topics such as: upward mobility, education for calibrations, etc. Finally, the Community grouplet is responsible for initiatives and events that foster a sense of connectedness. Any frontend engineer at Lyft can be a part of the Frontend Working Group.

All Frontend members are linked through the Frontend Working Group.

Apart from the above, we have a dedicated Frontend Infrastructure team, which exists as part of the general Infrastructure vertical and whose sole mission is to support and improve experience of the frontend developer. The members of this team are responsible for the creation and maintenance of Frontend Build, @lyft/service and all of the other pieces of software around it, along with documentation, help systems and developer assistance. Having a dedicated team for this important work has been a key for having a quickly iterative improvement process on frontend tooling and the software development processes themselves in all of the organization.

We all make Frontend possible

Frontend work at Lyft is important, diverse, and exciting. While our organization has become robust during the years, we are still very flexible and anybody that contributes can have the chance to create real impact. For a couple of examples:

  • A couple of frontend engineers proposed recently the internal adoption of xstate as a state machine engine; this is now recognized as an optional part of our state management stack.
  • A group of engineers is tackling low-hanging web performance fruit in our tech stack.
  • Another group is leading an internal initiative to rebuild end-to-end testing using the Cypress framework.
  • Another group of engineers is driving GraphQL adoption across the organization by building tooling and internal support.

For a couple of public examples of our work, you can check out:

  • the Lyft website, with info on all things Lyft;
  • our ride web page, where you can book a ride now, no app needed;
  • our open-source projects with frontend components, such as Clutch, our extensible platform infrastructure manager; also, projects formerly owned by Lyft and donated to the open-source community, such as Amundsen, a data discovery and metadata engine, or Flyte, a machine learning and data processing platform.

We are always looking for more collaborators eager to build Lyft together. If you want to be a part of this story, please consider joining our team!

Thanks to Andrew Hao, Jamie Cohen, Alex Ung, and Sheng Hong Tan for their collaboration in this article.

This article is also available in Spanish: eng-espanol.lyft.com

--

--