The Platform and Program Split at Uber: A Milestone Special
The change that shaped the engineering culture for years to come, and my take on Platform teams
👋 Hi, this is Gergely with a bonus issue of the Pragmatic Engineer Newsletter. The publication just crossed 100,000 newsletter subscribers, only ten months after it was started. Thank you for being a newsletter subscriber! 🙌
To celebrate this milestone, I’m opening up the first paid article for anyone to read for the next week, written almost exactly ten months ago. I hope you find it interesting.
As a reminder, if you’re interested in getting more frequent issues with in-depth content and actionable advice especially relevant for software engineers and engineering leaders, consider subscribing to the paid version.
Many subscribers expense this newsletter to their team’s learning and development budget, as it’s a great way to grow as a tech professional, and keep up with the industry. Here is an email you can send to your manager.
The Pragmatic Engineer Talent Collective has launched. If you’re hiring, apply now to start getting twice-a-month drops of world-class senior and above engineers and engineering managers/directors who have just entered the market. The first drop is out. Learn more and apply here.
Now, on to the article:
The Platform and Program Split at Uber
In the spring of 2014, Uber’s Chief Product Officer, Jeff Holden, sent an email to the tech team. The changes outlined in this email would change how engineering operated and shape the culture for years to come. The email kicked off with this:
“After a huge amount of data collecting, thinking and debating among many folks across the company, we are ready to launch Programs & Platforms! (Attached to this email) you’ll find out whether you’re on a Program or Platform team, and where your seat will be with your new team.”
It had only been three years since Uber made its first full-time engineering hire, and there were already more than 100 engineers, 10 Product Managers (PM), and 15 designers at the company by this time. Almost all engineering teams operated independently, owning their roadmap and projects. This was an evolution from the very early days of Uber when things got done on a project basis of people coming together, shipping a project, splitting up when done and moving to the next project.
The email explained how the current org structure would completely change; over a dozen teams replaced by 16 program and 11 platform teams, with every person allocated to either a platform or a program team.
Most of the teams would not be fully staffed, and more than 100 people would need to be hired across engineering, product and design, to staff these teams. The new teams were stack ranked by importance – for example, teams responsible for growing the supply of drivers were ranked much higher than those generating rider demand.
This email executed Uber's biggest engineering organizational change: creating cross-functional program teams and introducing platform teams. To date, Uber operates following the legacy of this change, of teams being either platform or program teams.
But what is this split, and why does it make sense? Let’s start with the definition of the two types of teams.
Program teams – often referred to as Product teams at other companies – represented between 60–70% of the engineering population. These teams organize around a mission and are optimized for rapid execution and product innovation. Programs were defined with the following characteristics:
Long-lived as opposed to just assembled for a short project. The teams were formed around a mission such as Driving Experience, Marketplace Efficiency, or APAC Growth. The teams owned a well-defined mission.
Cross-functional. Each team had the staffing to allow it to execute its mission. In practice, this meant a mix of non-engineers and engineers on a team. It was common to have a product manager, a data scientist, and even a business operations person on the team. Engineering was also cross-functional, with backend and native mobile engineers on most teams. Some teams had web engineers as well. Teams usually owned features in the Rider, Driver, or Eats app. To build and operate features, you needed to build and own backend systems and the client code.
External customers to the Tech org. Program teams would work directly with customers, shipping features they used. Customers were not only Riders, Drivers, Eaters, or Couriers, although they were the majority. Internal customers included Operations, Customer Support or Accounting, and other smaller business area customers such as Freight customers, Jump bike riders, and others.
Focused on a business mission. All program teams were focused on moving the needle for the business. If the business changed drastically, for example, because there was no more need to focus on growth, then the team would cease to exist. Over time, Program teams did change. They usually only grew. However, some teams got disbanded after not growing as rapidly as the business hoped. An example of this was Uber Rush, where the team split up after it did not grow as fast as the business had hoped.
When joining Uber, I started and worked on a Program team for a long time; Rider Payments. Our mission was to provide a magical payment experience for all riders. The team was a cross-functional unit of eight native mobile and backend engineers when I started managing it. A PM, a data scientist, a designer and a product operations person were also part of the team, though did not report to me, as an engineering manager. The team eventually grew to around 12 engineers before we changed the mission of the team.
Our customers were riders using the Uber app. We measured our business impact with metrics like incremental customers onboarded, incremental gross bookings generated, or cost savings generated. These metrics changed with every planning cycle, adapting to whatever the company was focusing on.
Platform teams own the building blocks that Program teams used to ship business impact. Programs are built on top of Platforms, which enabled Programs to move faster. All Platforms teams shared the following characteristics:
Focused on a technical mission. Platforms are focused on technical goals like scaling a key area, achieving performance or availability goals, or building an easy to extend and maintain architecture that serves multiple teams and areas.
Specialized and rarely cross-functional. As Platforms solve technology problems, it rarely makes sense for cross-functional teams to do so. A Platform team typically worked on one domain or stack. Most teams would only have engineers of a certain stack. Later on, some platform teams started to work with Technical Product Managers (TPMs) or product managers, but this was rarely the case early on.
Customers are engineering teams and are internal (usually). Most customers for a platform team are engineers of other program teams or, in rare cases, people from the business side also using the platform. This was also why lots of platform teams could just consist of engineers. Some – though fewer – platform teams might serve external engineering customers directly, such as a team shipping a development SDK.
Consumed by multiple “verticals” (Programs or Platforms). Each Platform would have multiple customers. This was also a requirement for a Platform team to own any functionality. If a service or functionality would only be used by one Program, that Program should own it, not a Platform.
As my organization grew within Uber, I spun out platform teams, creating the Payments Web Platform and the Payments Mobile Platform teams. These teams owned the payments building blocks that other teams across Uber could use to quickly ship web or mobile payments capabilities.
Creating a platform team tends to be a challenge for many engineering leaders, myself included. Securing headcount is rarely trivial, staffing the team from the start can be tricky, and defining what success looks like is less straightforward than with Program teams.
If you are building a platform team, as a subscriber, you have access to 🔒 this platform narrative document that I used when making a business case to create a new platform team.
Shared Program/Platform Characteristics
While programs and platform teams solved different needs, they both shared several attributes:
Single manager for all engineers. Every engineer on the team – regardless of their stack or specialization – reported to the same engineering manager, who headed up the team. The engineering team was one tightly coupled unit.
You build it, you own it. Whatever a team built, they owned the quality, the oncall, and ensuring things operated. This meant both Platforms and Programs typically had oncalls. There were very rare exceptions to this.
The same quality bar. Regardless of which team you were on, the quality bar was the same. Your code was expected to be tested and the functionality monitored. Some might be surprised to learn that Platform teams ran their own monitoring and alerting on the metrics they owned. Platform teams would add telemetry to almost everything they did and usually knew when their system had an issue before customers did. For example, the Developer Experience team would get alerted for issues with the Continuous Integration (CI) service and could start to investigate well before an engineer would report the same issue.
No permission needed to build. You do not have to be a Platform to create new services, modules, or reusable components. Many platform pieces started with a Program team building it. This newly built platform piece would then either become a Platform team itself, or might be handed over to a Platform team operating in this domain to own.
Program teams splitting into further Programs and Platforms as they grew. As a natural consequence of the programs and platforms approach, as most program teams grew they tended to split into more programs, and some into platform teams. Platform teams tended to own shared functionality and responsibilities across programs. This “splitting” became a natural process in most parts of the organization.
All of these attributes are tied to team autonomy. Team autonomy together with engineering autonomy is something that innovative, “Silicon Valley-like” companies “get,” and which traditional companies often struggle to understand and grant.
Landing Teams on a Best-Effort Basis
Uber took a bold and decisive path in implementing this organizational change. They chose not to do a gradual, area-by-area change. Instead, leadership announced a date when all splits would happen, and teams would be set up as landing parties; a bit like how a landing party “beam down” in Star Trek from the USS Enterprise to a planet’s surface. Moving to Program and Platform teams happened at the same time as the company moved to its new Market Street headquarters in San Francisco, bundling the two changes together.
Uber decided to restructure ahead of having the sufficient number of people in place for all “landing parties” to be complete. What this meant was several teams were still operating as skeleton crews and were expected to catch up with hiring.
In my view, Uber was able to pull this restructuring move off for a few reasons. First, engineering leadership knew with high certainty that hiring would not be a problem based on both recruitment forecasts and the investment in recruitment. To make these kinds of expansion calls, speaking with recruitment – and getting their take on what it takes to hire certain targets – is a key step.
More importantly, Uber leadership must have had very high confidence in the business continuing to grow, and to eventually outgrow even the existing structure in place. Making a change this impactful would hit productivity in the short term, but the teams would bounce back right after and carry on executing with increased efficiency.
Confidence that the business would keep growing proved correct. Uber not only grew the ridesharing business significantly, but it also started Uber Eats in the summer of 2014, Uber Freight in 2017, and several other big, bold bets within the business.
Problems Solved Related to the Old Structure
Before the change, Uber operated in a classic, functional organizational structure with Engineering, Product Management, Business Operations, Design, and Data Science, each operating in their own groups. Engineers were grouped in teams, but those teams did not include people from other disciplines like Product Management or Design.
Engineering teams at the time included Rider Operations, Driver Operations, Dispatch and Mobile. These teams did not have dedicated product managers or other functions assigned to them. Product managers tended to own projects and would often work with multiple teams.
I’d describe this approach as project-based, although strictly speaking, there were stable engineering teams. However, projects dominated the way work got done and how people organized.
Upsides of this project-based approachwere plenty:
1. Response time. Any time a new opportunity or threat came up, you could form a project and tackle it. Not much coordination was needed.
2. Flexibility. This structure adapts well when you have little idea what type of work will come up, even in the short-term. In the early days of Uber, this was true. It was unclear if responding to external events, seizing a new opportunity, or executing on the existing plan would come first.
3. Little planning and structure overhead. Teams practically self-organized themselves with projects, continuously responding to the biggest challenges for the company. As long as this setup worked well, why add more processes to planning and organizing teams?
Downsides of the project-based approach also started to show, though. For Uber, at that time, these were the main ones:
1. Difficult to prioritize as the company grows. With a small team and few priorities, project-based work was easy to juggle. But Uber’s business was already very complex by this time. The Driver and Rider app had many parts that grew in complexity, with more rules than the original app.
It wasn’t just app functionality; the business operations teams needed to execute on more and more one-off initiatives in different cities. Other business units – from finance to legal and others – also had projects to get done. Prioritizing several dozens of projects was becoming more and more difficult.
2. Many cross-functional projects launched as MVPs, getting little love afterward. After a project was launched, the launch team immediately split up. An engineering team would still own the project, but other people, like the mobile engineer, Product Manager or Business Operation person, would focus on the next project.
With the ad-hoc approach for cross-functional work, it was a lot harder to start a “follow-up” project. This was especially true for work that involved mobile engineers, as they worked in teams separate from all other engineering teams.
3. Starting new projects became more difficult to coordinate. The theory of “start a project anytime, with the right people” sounds great with the project-based approach. However, the reality was not nearly so simple.
Each project typically needed people with specific skills and sometimes domain experience. This might have been a mobile engineer, a designer or a business operations person. However, those people were typically working on other projects. So instead of starting a project immediately, new projects had to coordinate when all people would become available. More frequently, people would juggle several projects.
4. More silo projects and fewer cross-functional projects were started. Because starting projects across multiple groups was difficult, it was no surprise that more projects with no cross-functional coordination were started. For example, because all mobile engineers worked in the Mobile team and it was hard to “book” a mobile engineer, most teams started to work on features that did not involve mobile work.
Uber reached the point where it needed to prioritize executing on projects that were best for the business - and, to do so, it needed to address the underlying issue blocking these efforts.
5. The most important company objectives were cross-functional by nature. Uber realized that shipping the “easy”, but siloed projects, is not in the interest of the business or the customers.
Uber needed to make the change of enabling cross-functional work easier. The Program teams defined the company-wide priorities with logical groupings, and the company committed to staffing these teams for the long run. Platform teams were put in place to support Program teams, to allow them to focus on their business mission, and to own the shared foundations that many Program teams build on top of.
New Problems Created
This article is too long to read in an email. Continue reading online. The full article will be available for one week to read.