Making cross-cutting investments

Over the last few weeks, I’ve been thinking about approaches to influencing projects and teams across a large organization. I framed the exercise like this: suppose I have some organizational currency (headcount!) to invest. How do I nudge project trajectories in the most effective way?

Then, I talked to a bunch of peeps, looking for forces present in this problem space. There are probably many more, but these two piqued my attention. The first one has to do with the term of the investment: do I want to invest in several different things over time or do I mostly want to keep investing into the same thing? The second one has to do with how much control I want to have over the structure of investment: how much steering do I want to do with my investment? Mapping these two forces into thinking space, a few recognizable clusters emerge. 

A good example of low-control, permanent investment is donation. I find a team, recognize that it is doing important work and decide to help them by adding to their capacity to hire new folks. Based on my experience, this is more or less a permanent investment. Withdrawing donated headcount tends to be painful for all parties involved. Nevertheless, if the team’s goals are largely aligned with mine over the long term, and I have no qualms with their strategy, it’s a pretty good fit.

If I want a more temporary engagement, I need a different approach. One is to temporarily augment a team with a group of folks to accelerate a particular aspect of work. It’s exciting to imagine that such a team will drop in and race forth with uncanny precision. However, in orgs that have strong engineering practices and structures, augmentation is first and foremost a matter of learning to follow those practices and fitting into existing structures. “Who will review your CLs?” is the question to contemplate when considering the augmentation setup. They work well in homogenous organizations, when the members know the engineering practices well and are the people who can review CLs. Otherwise, this investment tends to offer less control than anticipated.

To gain a bit more control without permanence, I will likely try to incubate a team: seed it with good peeps, set up a resilient structure to help it stay on course, get it past the early growing pains, and let it go. Variants of this approach are found in research organizations and idea incubators, and I’ve seen it work. In the couple of times that I participated in the process, the biggest challenge was finding the right fit for the graduating team and then shepherding the team through often painful reintegration. At least to me, incubation felt more like an art rather than a repeatable process, but that just might be the lack of experience.

Finally, if I am seeking to invest in the long term while retaining high control, I am probably productizing, or reframing my desire to help in terms of a developer-facing product: a tool, a library/framework, an SDK, etc. This product must be good enough for the teams to want to rely on — and to get results that I want them to get. Note that this end result is a second-order effect (first, they want to use it, second, they produce desired outcomes), which is what makes this approach so challenging. On the other hand, precisely because of the indirection, this approach has something that no other approaches offer: the ability to influence multiple teams. Productizing is typically more demanding compared to others. It takes more effort and capacity to build an effective team that reliably ships a successful developer product and have the resilience to keep an eye on the outcomes I need. That last one is important. It takes just a little bit of stress and firefighting to fall back into the “let’s make developers happy” mode and forget the whole point of the exercise.

Heuristics will be discerned and codified

Here’s another developer experience pattern that I’ve noticed. When designing APIs, we are often not sure how they will be used (and abused), and want to leave room for maneuvering, to retain a degree of agency after the API is in widespread use. One tempting tool we reach for is the use of heuristics: removing the explicit levers to switch on and off  or knobs to turn from the developer surface and instead relying on our understanding of the situational context to make decisions ourselves. Unfortunately, when used with developer surfaces, heuristics tend to backfire. Developers who want those levers and knobs inevitably find ways to make them without us. And in doing so, they remove that agency that we were seeking in the first place.

Because heuristics are so tempting, this pattern is very common. Here’s the most recent example I’ve stumbled upon. Suppose you are a Web developer who wants to create an immersive experience for their users and for that, you want to make sure that their device never goes to sleep while they are in this experience. There’s an API that enables that, called the Wakelock API. However, let’s imagine that I am a browser vendor who doesn’t want to implement this API because I might be worried that the developers will abuse it. At the same time, I know that some experiences do legitimately call for the device screen to stay awake. So I introduce a heuristic: stay awake if the Web site contains a playing video. Great! Problem solved. Except… You want to use this API in a different scenario. So what do you do? You discern the heuristic, of course! Through careful testing and debugging, you realize that if you put a tiny useless looping video in the document, the device will never go to sleep. And of course, now that you’ve discerned the heuristic, you will share it with the world by codifying it: you’ll write a tiny hosted API library that turns your hard-earned insight into a product. With the Web ecosystem being as large as it is, the library usage spreads and now, everyone uses it. Woe to me, the browser vendor. My heuristic is caught in the amber of the Web. Should I try to change it, I’ll never hear the end of it from angry developers whose immersive experiences suddenly start napping.

It’s not that heuristics are a terrible tool we should never use. It’s that when we decide to rely on them in lieu of developer surface, we need to anticipate that they will be discerned and codified — sometimes poorly. This means that if we wanted to rely on heuristics for some extra flexibility in our future decisions, we’re likely to get the opposite outcome — especially in large developer ecosystems.

Hosting and hosted API design perspectives

When discussing API design strategies, I keep running into this distinction. It seems like a developer experience pattern that’s worth writing down.

Consider these two perspectives from which API designers might approach the environment. The first perspective presumes that the API implementation is hosting the developer’s code, and the second that the API implementation is being hosted by the developers’ code.

From the first perspective, the API designer sees their work as making a runtime/platform of some sort. The developer’s code needs to somehow enter a properly prepared environment, execute within that environment, consuming the designed APIs, and then exit the environment. A familiar example of designing from this perspective is the Web browser. When the user types the URL, a new environment is created, then the developer’s code enters the environment through the process of loading, and so on. Every app (or extension) platform tends to be designed from this perspective. Here, the developer’s code is something that is surrounded by the warm (and sometimes not very warm) embrace of the APIs that represent the hosting environment.

When I design APIs from the second perspective, the developer’s code is something that hosts my code. I am still offering an API that is consumed by someone else, but I don’t set the rules or have opinions on how the surrounding environment should work. I just offer the APIs that might be useful. Typically, this perspective results in designing libraries and frameworks. For example, I might write a set of helper functions that provide a better handling of date math in Javascript. This tiny library can run in any Javascript environment, be that server or client. It can be hosted by any app or site that needs date math. This “run wherever, whatever” is a common attribute of this API design perspective.

There is the growth/control tension that seems to map into these two perspectives. Hosting perspective exhibits the attitude of control, while hosted perspective favors the force of growth. As with any tension, complexity arises along the spectrum between the two.

A Javascript framework (a hosted API) that has strong opinions about its environment (wanting to be a hosting API) will have challenges maintaining this environment, since it is ultimately incapable of creating it. Back in the day when I still worked in the Web Platform, I’ve had many discussions with framework authors who wanted us Web Platform folks to give them the option to create clean environments. This desire to shift from hosted to hosting was not something I recognized back then and now wish this article existed to help me reason through the struggle.

Similarly, a hosting API that wants to grow will be pressed to make the environment more flexible and accommodating. Going back to the example above, we Web Platform folks were experiencing that pressure, the force that was pulling us away from hosting and toward a hosted API design perspective. After that shift, the code that renders Web pages — the fundamental building block of the Web Platform environment — would become just one of the libraries to pick and choose from.

It is also important to note that, using Hamilton Helmer’s classification, the existence of a hosting environment is a form of cornered resource. It’s something that only becomes possible to have when the API designer has the luxury of a significant quantity of willing hosted participants. In the absence of eager hordes of developers knocking on your door, taking a hosting API design perspective is a high miracle count affair. When thinking about this, I am reminded of several ambitious yet ultimately unsuccessful efforts to “create developer ecosystems.” There are ways to get there, but starting out with the hosting API design perspective is rarely one of them.