Principles - Processes - Categorization - GitLab the Product - Being a PM - Performance Indicators - Leadership
The direction for the GitLab product is spelled out on the Direction page. This document provides lessons and heuristics on how to design changes and new features. Our iterative process is demonstrated in a blog post.
Much of our product philosophies are inspired by the Ruby on Rails doctrine of 'Rails is omakase'. I highly suggest reading these.
These are core principles we believe strongly in. The goal is to build a PM system that fosters and honors these principles, in a way that works for GitLab.
From development teams to marketing organizations, everyone needs to collaborate on digital content. Content should be open to suggestions by a wide number of potential contributors. Open contribution can be achieved by using a mergeable file format and distributed version control. The mission of GitLab is to allow everyone to collaborate on all digital content so people can cooperate effectively and achieve better results, faster.
Ideas flow through many stages before they are realized. An idea originates in a chat discussion, an issue is created, it is planned in a sprint, coded in an IDE, committed to version control, tested by CI, code reviewed, deployed, monitored, and documented. Stitching together all these stages of the DevOps lifecycle can be done in many different ways. You can have a marketplace of proprietary apps from different suppliers or use a suite of products developed in isolation.
We only ship in a Minimal Viable Product (MVP) style. We call it Minimal Viable Change (MVC) because our business model is focused on adding additional value to our integrated product suite instead of building separate, new products.
MVC means we deliver the smallest possible solution that offers value to our users. To avoid feature bloat, we rely on user research to validate whether our idea addresses a market need in a desirable way. This approach sets us up to expend the smallest possible amount of effort to build new capabilities, while learning more about how to best add additional functionality over time.
While an MVC may not have the robust functionality of a fully developed feature, it should still address fundamental user needs through a bug-free and highly usable experience. The minimal viable change should not be a broken feature.
Advantages of an MVC approach:
When considering how to scope a feature for a release remember it is ok to ship an "incomplete" feature to customers - assuming it still offers value and is not broken. For example, you could ship a feature that lacks a completed interface but still adds value if the user chooses to use it. See this MR as a great example of a release post item shipping a truly minimal feature. Consider existing workflows and understand the impact on overall user experience as you release your feature. In terms of talking about your feature, it's ok to add a release post item that announces your incomplete feature (making clear that it is an early iteration, and points to the direction for the feature) and follow-on in a later release post with a new item when you've completed more of the functionality.
An MVC approach is a byproduct of our spirit of iteration. That means we break problems down as small as possible, use throughput as a performance indicator, and focus on reduced cycle time. Thinking iteratively is not always intuitive, and breaking certain topics or projects down can be challenging. Here's a helpful video from our CEO with guidance on how to think more iteratively.
Here is a great video that illustrates how to build MVCs using Iteration. It shows Lego climbing obstacles. The first design fails. The second one can climb a book and so on. It also illustrates how modularity and good interfaces help with iteration as things get complex.
An MVC approach allows for maximum feedback while iterating. To help gather that feedback, Product Managers are encouraged to create feedback issues (example) to consolidate suggestions and experiences from users. Consider mentioning the feedback issue in any release post items and related implementation issue(s) for awareness.
Just because something is not invented here doesn't mean it doesn't have a perfect home within our solution. GitLab is an Open Core product and is part of the broader ecosystem of Open Source tools in the market. Every day there are new innovative tools out there that solve real-world customer problems; we should not be afraid of embedding these tools into our own products in order to solve those same problems for our customers too. Leveraging existing technology allows us to get to market much more quickly, to contribute to Open Source (and help strengthen Open Source as a whole), and allows us to focus our own people on making GitLab itself better. Building professional relationships with these tool creators also is a positive for GitLab since they may have important user perspectives around your categories.
We have achieved many successes following this approach:
There are also many more examples throughout the company where this has been successful. As a product manager you should be monitoring the world of Open Source as it relates to your area to see where new innovative tools are being developed, and not be afraid of integrating those. One thing to keep in mind, integrating could be anything from a blog post describing how the tool works together with GitLab all the way up to bundling it inside of our own installation, and this can evolve iteratively.
As an application development tool, we understand the natural inclination to create an array of buttons to press and knobs to turn.
We believe however that more options are not necessarily better, and that our users are better served by an application with reduced complexity yet still contains the features they need.
We admire other convention over configuration tools like Ruby on Rails (that doctrine of which perfectly describes the value of integrated systems), Ember, and Heroku, and strive to offer the same advantages for a continuous delivery of software.
Furthermore, Ruby on Rails has been of massive influence to the Ruby community. Uplifting it, and making it more powerful and useful than ever before, for many more usecases. We want GitLab to be to Kubernetes, what Rails is to Ruby.
You should prefer choices that are well thought out and based on current best practices. Avoid unnecessary configuration. Avoid configuration to support fragile workflows.
When considering adding new configuration, we follow the following principles:
Sometimes fast deployments are needed to fix a service or application outage that can cost a business money and reputation, we understand time is of the essence in these situations. That’s why we believe giving the team control over this is important in crucial moments of the development lifecycle
gitlab.yml
Product Managers at GitLab are frequently confronted with the choice of whether to add new configurations or not. These can frequently be times where an outside perspective is important. That's why we've created the option to request a New Config Review.
Here's an example of how to consider whether to add new configuration. Let's say you are proposing we add a checkbox or two radio boxes in a feature dialog box. Think carefully about what users really want. Most of the time, you'll find you really only need one solution, so remove the other option. When two possible choices really are necessary, the best or most common one should be the default, and the other one should be available. If the non-default choices are significantly less common, then consider taking them out of the main workflow for making decisions, by putting them behind an Advanced configuration tab, for example.
Avoiding configurations is not always possible. When we have no choice, the secondary priority is to configure something in the GitLab interface.
A configuration should only appear in a file (gitlab.rb
or
gitlab.yml
) as a last resort.
gitlab.yml
is the configuration file used by the Rails application. This is where the domain is configured. Other configurations should be moved to the UI as much as possible and no new configurations should be added here.gitlab.rb
is the configuration file for Omnibus-GitLab. It acts not only as
an abstraction of the configuration of gitlab.yml
for GitLab-Rails, but also
as the source for all configurations for services included and managed within
the Omnibus-GitLab. Newly introduced services probably need to be configured
here.When you have to add a new configuration, make sure that the features and services are on by default. Only add a configuration line to either of these configuration files if the feature or service cannot be fully disabled from the admin UI.
.gitlab-ci.yml
If the decision to add a configuration follows the principles above, add it to the repository-specific CI configuration options and be sure to default it to the option that results in the best user experience. We are much more liberal with additions to CI configurations than Instance configurations.
Within each stage, the learning curve must be at least comparable to our best-in-class competitors, with clear, cohesive workflows, a highly usable interface, and comprehensive documentation. Product works closely with the User Experience team to achieve our user experience goals.
Below are some general user experience principles we should always keep in mind. Additional UX principles to familiarize yourself with can be found in the UX Department strategy and GitLab's Pajamas design system.
Using GitLab should be easy. Users should be thinking about the applications they are building and teams they are collaborating with, not about how to make our app work. Don't make users think!
This sounds obvious, but it can be hard to keep things simple as an application becomes more complex, with more features and more options to cover more use cases and more user types.
The good news is that the product designer assigned to your stage group has a high level of expertise in how to simplify the complex, and how to make decisions about when to add or avoid complexity. Involve product design in all changes that impact the UI.
Many crazy, over-ambitious ideas sound like they are impossible just because no one else is doing them.
Since we have amazing engineers and a culture of shipping minimal viable changes, we are able to do a lot more 'impossible' things than others.
That's why we're shipping merge conflict resolution, why we shipped built-in CI before anyone else, why we built a better static pages solution, and why we're able to compete.
Here at GitLab, we are an ambitious company and this means we aim for big things with every release. The reality of taking chances and planning aspirationally means that we won't always be able to deliver everything that we wanted to try in every release, and similar to our OKRs, we believe this is a good thing. We don't want to shy away from challenging ourselves and always want to keep a sense of urgency, and aiming for more helps us do that. Also see the importance of velocity
We arrived at our preference for ambitious planning after measuring our velocity and finding that our velocity was unchanged whether we scheduled ambitiously or scheduled for providing slack.
Feature discoverability is important for helping novice and experienced users find features that benefit them, thereby increasing the value of GitLab for them. And the more users see and try our features, the faster we can get feedback to improve them.
However, when taken too far, this can have the unwanted effect of annoying users. The end result is that the user loses trust in GitLab, and they no longer take the time to carefully parse text and other UI elements in the future. Even worse, they might leave GitLab because of this degraded experience.
Work with your product designer to improve the discoverability of your product. The Pajamas Design System has a number of patterns that support discoverability. We can also design new patterns. The Growth team can also help you with this, as they think about things like onboarding new users and promoting feature use within the app while supporting, not annoying, the user.
The following are a few illustrative examples and best practices. Dos and Donts, general best practices, examples and more details are available in Pajamas.
Banners draw attention to new features or features that have not been enabled.
Banners should be used sparingly. Think of this: Your co-worker is hard at work in front of their computer, and you suddenly tap their shoulder or yell at them to tell them about some new cool widget. You better have a good reason for that: that widget better be awesome.
Back to the analogy: Your co-worker said they don't care about that new cool widget. Never, ever, ever, bring it up again. They told you they don't care, and you need to respect that.
Alerts allow the application to pass along relevant system information to the user without impeding their journey. Alerts should guide the reader to an actionable next step. Alerts without actionable next steps induce anxiety and can slow down resolution.
Some important considerations when adding alerts:
Leveraging navigation is an effective design paradigm to introduce a user to a new feature or area of GitLab.
Back to the analogy. We're not going to bother our co-worker with 5 different cool new widgets at the same time.
As the GitLab userbase and team members who work on GitLab continue to grow we need to support both our users and team members by helping to connect users who may be interested in speaking with a member of the sales team to that particular person. We can call this a Product Qualified Lead or a PQL.
Our goal is to develop a world-class PQL system whereby we monitor product usage to understand and constantly iterate on what constitutes a usage-based PQL and provide a unified intelligent interface in the product where users can submit a hand-raise, start a trial or upgrade touchlessly.
By monitoring product usage, usage PQL volume, SAO rate, and ASP we will be able to work in partnership with marketing and sales to ensure we’re sending high quality leads to the sales team.
In the product experience, we will develop an intelligent module for feature discovery moments whereby we help recommend what we believe should be the preferred option for the user whether it’s a hand-raise, trial or touchless upgrade by updating the default CTA based on their usage of the product along with demographic and firmographic data. This experience will be present on both SaaS and self-managed instances for air-gapped instances the CTAs will provide the user with external URLs to visit to complete the associated step. This experience should be able to be deployed by any stage to further their paid adoption rate.
Users can only experience GitLab's value when they actively use the product features. Therefore the Product team's mission isn't only shipping features and building products, but also driving usage and delivering value.
There are two frameworks we use to think about driving GitLab's product usage: we use the AARRR framework to think about how to drive a single feature's usage, and use the Customer Adoption Journey to think about cross-adoption of product features. These two frameworks are also interconnected with each other.
AARRR stands for Acquisition, Activation, Retention, Revenue, and Referral which is often referred to as "Pirate Metrics". These five words represent the customer journey and the various means a product manager may apply Product Performance Indicators to drive a desired behavior in the funnel.
While the AARRR framework is commonly used to drive overall active users, it is also a great way for PMs to think about how to drive feature usage.
Add AARRR funnels for your stage or group's Product Performance Indicators directly with mermaid markdown. It's easy if you use this live editor.
Product managers can use these various states to prioritize features that drive a desired action. This could mean focusing on the Activation metric to drive awareness and generate more top of funnel
leads. As an example, in the Release stage the Release Management group tracks actions on the Release Page in GitLab. Users that view a Release Page have been acquired
and those that create a release on a Release Page are activated
users. The Product Manger can choose to target features that drive users to view the Release Page more, resulting in a greater interest in the number of users that become activated and create their own Releases.
GitLab is a complete DevOps platform. Our customers get the most value out of the GitLab product when they use multiple features together. Below is the most common path our customers follow to adopt GitLab's product stages.
As PMs, in addition to driving usage of individual features, we should also proactively think about how to design product and user experiences to help users adopt more stages and features, therefore benefiting more from using GitLab.
The foundational user journey is from Create -> Verify. This is the most common combination of stages, and we believe when users experience these two stages they begin to understand the broader power of a single application for the entire DevOps lifecycle. We are working on several projects to increase the number of users enjoying Create and Verify together. Examples:
Note: There are numerous potential variants to this adoption journey, but it's important to keep this representation simple and consistent. Please check with Scott Williamson first before making any changes to the adoption journey image.
Shipping only MVCs can result in a large set of loosely connected pieces that don't necessarily combine into a single, great user experience.
An obvious solution to this would be to plan out the future in detail, creating a long-term detailed plan. However, this is unwanted as it can restrict your flexibility and ability to respond to changing needs or feedback.
Flow One offers an alternative. You draw out a workflow consisting of MVCs (that can be shipped individually). The workflow should only cover a specific, narrow use-case, and nothing more.
This means you:
Flow One should cover the first iteration of a particular workflow. After this, individual MVCs can be introduced to expand the use-cases or loosen the assumptions (e.g. from a feature that can only be used if you're using feature branches, to one that works for other git strategies).
Using data to learn from our users is important. Our users are spread across GitLab.com and self-managed instances, so we have to focus our efforts on learning and providing benefit to both when we decide to collect more data, or build and use additional analytics tools. If we do this, we can help make the rest of the company successful as well. This means that we should:
Per GitLab Stewardship, we will not introduce artificial limits in Core. Artificial means arbitrarily setting a small number (such as: 1) as a limit on a given GitLab object category, that would incur no additional effort or cost had we chosen a larger number. The additional effort includes product, design, and engineering effort to create the feature in the first place, and to maintain it over time.
For example, GitLab Core has the issue board feature in every project. In GitLab EE, each project supports multiple boards. This does not mean that Core has an artificial limit of one board per project, because there is additional effort to manage multiple boards such as supporting the navigation interface, and all the associated engineering work.
This principle does not apply to our SaaS offering as limits are occasionally introduced to limit our hosting costs and protect other users from potential abuse. As an example we have shared runner minute quotas and implement rate limiting.
After making a tier decision on a new feature, we should strive to maximize the number of users who can use it.
As part of this objective, we should avoid building instance-level features when possible. Building at the instance level (in the admin area) leads to a separation between GitLab.com and self-managed and limits your audience to self-managed customers only:
Historically (and even net-new proposed features) we've often started with an "instance-wide" mindset which then means we need to iterate and adjust features to work at a group-level. This often delays functionality for our SaaS customers and makes GitLab.COM feel like a second-class citizen.
There are factors that may justify an instance-level feature, like engineering efficiency and high infratructural cost, but we should always have a clear view on how we might bring the feature to GitLab.com and clearly document why we started with the instance-level in the issue.
We're discussing enforced workflows in this issue.
Enforced workflows should be avoided in GitLab. For example, there are three issue
states (Open
, In Progress
(as of 10.2), and Closed
), and any issue should be
allowed to transition from one state to any other state
without workflow restrictions. (Roles and permissions is a separate concern.)
A comment on Hacker News perfectly details what can go wrong when enforcing workflows:
"The down side for the true end-users, those who actually use the software day-to-day, is that most business processes are awful. If your experience is the hellish existence that I see strolled about on threads where JIRA comes up …:
But that comment also specifies the advantage:
"JIRA's most powerful feature is that it affords for mapping businesses processes onto software. This is incredibly compelling to enterprise customers. Software that enforces workflows, procedures and requirements can be an incredible lever and JIRA's price point makes build vs buy decisions an absolute no-brainer."
We should ensure that GitLab makes it easy to help with enterprise workflows:
When considering a customer need for enforcement or limitations:
As an example, customers requested instance-wide enforcement through required CI jobs. Doing this would have been a mistake. Instead:
While workflow enforcement should be avoided in most cases, there are organizations that rely on enforced workflows for a variety of reasons. These organizations have problems adapting existing workflows as they move to GitLab and as a result, we should consider allowing some enforcement at the group level in order to balanace team efficiency and organizational policy. Page 79 of Accelerate outlines "teams that reported no approval process or used peer review achieved higher software delivery performance." As we implement features to allow organizations to enforce workflows, we should do so at the group level and default them off. GitLab should be a product teams use to accelerate product development, but flexible enough to solve for requirements of all sizes of organizations.
Small primitives are building blocks in GitLab. They are an abstraction not at the technical level, but truly at the product level. Small primitives can be combined, built-upon further, and otherwise leveraged to create new functionality in GitLab. For example, the label lists in issue boards use the smaller primitive of labels.
They are especially powerful because they usually take less effort and provide higher leverage than you would get from a more "complete" but standalone feature. Think of how simple Unix command line utilities can be chained together to do really complicated things, much easier (and certainly more flexibly) than you could have done with a dedicated tool.
When iterating on GitLab, strongly consider using small primitives instead of creating new abstractions, especially when considering MVC features that will provide the foundations for further improvements. To do this you can start with easy to apply concepts that meet the needs of intermediate to advanced users; from here document the usage clearly and be sure to think about discoverability. The UX can very often be refactored or enhanced later when there's a demonstrated need for refinement, onboarding for less sophisticated users, or other new abstractions needed that were identified through real-world usage.
GitLab's vision is to be the best single application for every part of the DevOps toolchain. However, some customers use tools other than our included features, and we respect those decisions. With this in mind, it's sometimes valuable to integrate with 3rd-party services and products to help bridge the gaps in their toolchain. While a single application is the best approach, multiple applications that work well together is better than ones that don't.
With this in mind, below are some product guidelines to consider:
Note - We intend to provide a place where everyone can contribute, such as code snippets, project templates and CI/CD templates. Marketplaces are traditionally transaction based, where users are purchasing solutions. GitLab CI/CD templates on the other hand, will offer an in product experience for consuming templates for YAML configuration from a library of GitLab maintained templates.
Closed source software vendors commonly depend on plugins and commercial marketplaces because:
Because GitLab is an open core product, third parties can add functionality directly to GitLab. Adding directly to the GitLab codebase (as opposed to building a plugin) may mean more work for them and will limit the ways in which they can charge for that functionality.
However, for users of GitLab, this has significant advantages:
And for developers of GitLab including the third parties, this has significant advantages as well:
Overall, we believe that this approach creates the best possible experience for both the users of and the contributors to GitLab, and to that end we encourage people to contribute functionality to GitLab directly.
If adding code directly to GitLab isn't an option, we encourage third-parties to integrate through our APIs.
Note: GitLab does support plugins that respond to system hooks, which tie directly to application events and are primarily used for administrative purposes such as auditing, logging, and other administrative tasks.
While our big, hairy, audacious goal spans all development processes, personas, and use-cases, there are primary targets in each one of these venues. When considering prioritization we should first aim to provide complete maturity for developers building cloud native applications in a modern way prior to moving to other development methodologies, personas, and application types.
When developing features to compete with existing competitors, make sure to solve problems for modern development teams first, and then see what's missing for legacy teams. e.g. For project management, make great project management capabilities for teams doing conversational development, lean, or even agile development before doing Scaled Agile Framework (SAFe) or waterfall.
It's important that modern first does not mean non-modern never. It means that we should first learn how teams are using the feature in a modern way, and then see what's missing. The modern way provides the path forward, and then we can add customizability or the path to modern for teams who are not quite there yet.
Our strategy includes going after a lot of new personas, going from developers to operations, security, product managers, designers, etc. But when developing features in these new areas, it's important to remember to start with the developer. If we can make security great for developers and then great for security professionals, we'll be much more successful.
Development teams deploy to tons of different platforms, from bare metal to cloud VMs to cloud-native Kubernetes clusters. We build features for cloud-native first, and then support the rest. This allows us to focus on where development is going, and deliver solutions that every company aspires to use eventually, even if they're not ready to today.
By focusing on next-generation development flows, personas, and use cases - we build features and experiences where our initial users are in the relatively small population of early adopters. While we might build experiences to support them today, we presume there will always be a much larger population of future users of these experiences. Therefore, we optimize GitLab to support the larger number of current and future adopters of next-generation principles - those who are beginning to operate in the workflow (modern), team setup (developer first), or application architectures (cloud native) we support. We focus our investment in the most modern workflows that will best support those current adopters. This will come at the cost of sustained investment in initial workflows for early adopters.
For example - we first provided an application log experience based on direct scraping of logs via kubectl. After adding support for installing Elasticsearch to your Kubernetes cluster, we should not continue to invest in the kubectl log view as we'd recommend newcomers to use Elasticsearch.
We provide customer support to paying customers on all features that are in the tier of their paid license as well as any lower tiers. This means a feature in Core, should get customer support in all paid tiers. For example, when there is a feature that is available in the lowest paid tier, but only has customer support in higher tiers, the feature should be removed from that lowest paid tier. In accordance with our stewardship policy we can never remove features from Core into paid tiers, but we can build additional features around it which are available to paying customers only.