Platform lesson #5: Distinguish customer-unique and customer-first functionality
The idea behind platforms is to share functionality between different products and make it available to as many customers as efficiently and quickly as possible. This is one driver for continuously incorporating new features into the platform. Incorporating new features can be done using a product-first approach or a platform-first approach.
In the product-first approach, the products built on top of the platform first incorporate new functionality in a product-specific fashion. Once two, three or more products have it, the functionality makes it to the platform’s backlog and a generalized, generic version of it is incorporated into the platform, replacing the product-specific versions. When using the platform-first approach, new features are immediately incorporated into the platform and made available for all products.
Even though the product-first approach can easily be viewed as less efficient, there’s a caveat: in practice, it’s often quite unclear what the best way is to realize new functionality. Therefore, using the product-first approach, the functionality is first realized for each specific product and once it has matured to a point where it’s clear how it should be realized, it can be generalized and incorporated into the platform.
The risk with the platform-first approach is that it may easily result in significant amounts of rework. Feedback from customers and the product teams will often require the platform team to make several changes to the functionality. Of course, the team can decide to deprioritize these requests, but that results in a suboptimal realization of features.
Many companies aspire to have roadmap development, ie functionality driven by their strategic priorities. In practice, however, much of the features on the roadmap are the consequence of customer requests.
Few companies are successful without being responsive to their customers. Consequently, many companies and their salespeople, product managers and senior leaders tend to say yes whenever a customer asks for something. Although this is fine when you’re building bespoke systems and customers are paying you for your time, it easily becomes problematic when selling a product or a platform and there are many, potentially conflicting, requests from customers.
The challenge is that each request needs to be triaged into two or three different buckets. The primary question is whether a particular request is customer-first or customer-unique. Customer-first refers to functionality that one customer happens to be the first to ask for but that over time will become relevant for other customers as well. This functionality should of course be incorporated into the platform over time. Customer-unique refers to functionality that’s unique for that specific customer and that won’t be relevant for other customers at any point in the future.
The first question concerning customer-unique functionality is whether it’s possible to say no to the request without significant consequences to the customer relationship. If the functionality needs to be built, in the ideal case, we can do so at the other side of a customization API. Thus, neither the product nor the platform will be affected. The alternative is to include the functionality in the product or platform and then use feature toggles to activate or deactivate it. Most companies use some form of licensing mechanism to configure, typically at startup or runtime, what functionality each customer has access to.
The problem with customer-specific functionality in the platform is that it drives up variability and the number of variation points in the system. When many customer-unique features are included, the dependencies between variation points as well as the variants for each variation point explode. This makes it exponentially harder to predict the implications of changes and additions to the platform code and has at least two significant negative consequences. First, developer productivity tends to plummet as so much analysis and design have to be done to ensure that additions don’t break legacy functionality. Second, despite this effort, many quality issues will slip through anyway, resulting in dissatisfied customers and many problems being identified in the field rather than during testing. This often leads to a third consequence: a slowing down of the release cycle as the company tries to compensate for the quality issues in the field by investing more and more time and effort into testing and a staged release process where new versions are tested longer at lead customers before being made available for all customers.
There will always be functionality requested by customers. Some of this functionality will be useful for more customers — the customer initially requesting it was simply the first to ask for it. Other functionality is so specific to the unique context of the requesting customer that it will never be used by others. Although it’s fine to incorporate customer-first functionality into the platform and then generalize it to other customers over time, we should be very careful to include customer-unique functionality. Ideally, we should provide that functionality outside the platform on the other side of an API or decline the customer request. If we do decide to incorporate it, we should ensure that it makes financial sense as the majority of costs related to software are accrued after the initial development of the functionality. Remember, being customer centered doesn’t mean accepting any customer request but rather carefully balancing all customer requests and your roadmap development to ensure maximum value for all customers.