Sustainable Delivery in Engineering

How can we as engineers deliver quickly, with quality at a sustainable pace over time? I share some of the opinions I have formed.

Sustainable Delivery in Engineering

Issue No. 1

This is a project by Jeremy Brown. I write about topics that I care about, such as building high performing teams that make great products, culture, leadership and technology.
As I'm building this newsletter (and a podcast and YouTube channel) in the open, you will get updates on this project here from time to time.

I originally wrote this week's topic for a skills test I did during an interview for an engineering role. The original question was, "What is your operating system to ensure that the team sustains this ability over time?". I've reshaped parts of my original answer as I've had a little more time to work on this.

💬 In this issue, I cover:

  • High-level principles of delivery.
  • The types of work and how to manage them.
  • Breaking things down into small product increments.
  • Showing the result of our work through demos.
  • Some high-level thoughts about quality.
  • How we often have to alternate between iteration and investment.
  • Some helpful metrics.

🦫 Sustainable Delivery in Engineering

How can we as engineers deliver quickly, with quality at a sustainable pace over time? Of course, there is no silver bullet. I wanted to start my first newsletter with some of the opinions that I have formed over time.

A short definition upfront. I use the word outcome here a lot. It is intentional. I define an outcome as a change in human behaviour that impacts business results. See "Outcomes Over Output: Why customer behavior is the key metric for business success" by Josh Seiden.

📏 High-level principles of delivery

I have a few principles that I want to define before I describe my operating system to ensure sustainable delivery over time.

  1. People must feel safe at work and good about the kind of work they are doing. Psychological safety is a prerequisite for any high performing team.
  2. Prioritisation by the value of the outcomes delivered.
  3. Optimise for finishing work before starting new work.
  4. Reduce uncertainty—de-risk unknowns early based on the level of risk. Risk should decrease over time. Before implementation, every activity's goal should be to arrive at a testable hypothesis. Every step we take in delivery should reduce risk.
  5. Murphy will visit us - anything that can go wrong will go wrong, or assumption is the mother of all f-ups.
  6. Use the Pareto principle for how we approach work and who works on what.
  7. "Show, don't tell". We should demonstrate working software every week. Building software and showing what we have made should happen regularly. Showing is a lot more powerful than telling.
  8. Everyone should feel safe stopping the production line by pulling the Andon Cord.

🗂 Types of work

The work of an engineering team generally falls into two categories.

  1. Outcome-oriented: work that creates an outcome or achieves something of value for the user.
  2. Chores or overhead work: we have to do these items, but they provide no apparent outcomes or value to our users.

I prefer to keep these two categories separate (I have used more in the past, see Investment Type below).

Outcome-oriented work should be in a backlog ordered by user value. The hypothesis around the outcome should define the value we aim to deliver for our users. In some companies I have worked at/with, we have given these items an actual monetary value to the company. I'm a big fan of establishing a standard set of metrics, such as a North Star Metric Framework. Don't forget to WSJF (Weighted Shortest Job First).

🏋️Work in Progress

Teams should work on a maximum of two particular initiatives/items/projects/features at a time. Ideally, we should only be doing one big item and one small item. They should never be working on two significant initiatives at the same time.

🥒 Product Increments

When teams pull an initiative from their backlog, they need to break it down into slices of work. I prefer to take a user story mapping approach to generate product increments or "slices of value" for the user. Then deliver the work progressively under a feature flag to production. Progressively means developers commit and deploy their work to production at least once a day.

Product increments should have the following properties:

  • Small. Product Increments are one to three weeks of work, no more. One or more product increments form a feature or project.
  • High-quality. Every time we complete a product increment, things should be better than when we started. Our codebase and the user's experience shouldn't degrade. (this might not apply where our product increment is a prototype used for discovery and de-risking purposes). By doing this, we preserve our ability to deliver value over time. When we complete a product increment, it should be releasable somehow. We may only release it to a subset of users, but work should be completed in a clearly defined manner.
  • Understandable. We need to use names for product increments that convey the value we are delivering. Any non-technical person in the company should understand what a product increment does. A good model I have come across is "[human behaviour or value provided] by [approach]." Giving a descriptive title allows everyone to understand what is happening and why. E.g., "speed up search results for users of the assignment page by implementing ElasticSearch." Non-technical people understand the value part. Engineers will know what we're doing from the approach part.
  • Have a clear outcome. Every product increment delivers value.
  • Atomic. If we are working on a project or feature with many product increments, we should be able to stop partway. Even if we don't finish all product increments, we should have delivered an outcome or value at each stage.

I think a product increment should be between one and three weeks of work and no more. One to three weeks is short enough for people to think about the scope of work and be reasonably accurate.

🗺 Planning for Product Increments

There are many ways we can deliver a project or feature. I have learned from Lean and other forms of thinking to generate multiple viable solutions instead of just one. We can do this by playing with the sequencing of how we break up our work.

Teams should try to develop three to five different ways to sequence a project. Then, we can better discuss the trade-offs between the various options and choose the best one.

Ways to think about delivery I have seen include:

  • When will customers have contact with our work? Moving customer contact forward provides us with information earlier and tests our assumptions. A good pattern for successful delivery is early customer feedback, followed by increasing customer contact over time.
  • What information will we learn, and when? We should do riskier product increments early to explore areas we are less confident. Or we might do a product increment where we test our assumptions early on.
  • When will things be in production and integrated? It is better to start with an end-to-end skeleton system and add more meat to the bone. When teams rely on last-minute integration or try to deploy to production at the end of the project, I tend to feel nervous.
  • What options do we give ourselves? Can we pivot halfway through the project? Can we "trim the tail" of the work earlier? Ideally, we do the highest value work in the first few product increments. Later increments deliver decreasing value (Pareto principle).

The goal is to work in tiny batch sizes with a very low WIP. Also, to have value flowing continuously to users.

📺 A short word on demos

I believe very strongly in "show, not tell", as I wrote earlier. Showing our work is inextricably linked to the act of building. Showing the results of our work via demos and storytelling is more powerful than telling. Demos are compelling.

Teams should ideally use weekly demos to show their work to their stakeholders. Ideally, the person who did the job should do the demo.

🚪 Quality Gates

I believe in having a solid definition of ready (DoR) for work that enters work in progress and a similarly high bar for the definition of done (DoD). Teams should operate with a zero known bug on release policy (with plenty of testing defined in the DoD). Quality matters and low quality slows you down.

🧹Separate Backlogs for Chores

Chores work best if they are on a different Kanban board from outcome (feature) delivery and are not on the product backlog. So instead, we can maintain a queue ready to go in the first column of this Kanban board. We set a WIP limit of what we are working on so that the team have to decide what is important enough to get a slot.

Teams should then decide a percentage of time to do their "chores" (e.g., one day a week or one person dedicated per week) and spend the rest working on outcome-oriented work.

This way, chores don't overwhelm outcome-oriented work. In addition, having separate boards lets the team track progress better by work category.

🗂 Investment Type

As noted above, I have tracked the "types of work" we are doing as a team in the past. I have heard this called "Investment Type", and I love the term. It helps us to help track what type of work we are doing. By monitoring our investment type, we seek to answer the question, where and how is our time spent? Is this how we planned to spend our time? Should we stop or start doing something?

Investment Types that I have used in the past:

  • Unplanned Work: Unplanned work will always creep into our to-do list. We need to identify it and what has caused it. We usually do unexpected work because the cost of delay is high or urgent. We then prioritise it and fix the issues immediately/alongside everything else that we have going on, rather than deferring them to our backlog or a future cycle. Unplanned work includes bugs, customer support requests, production incidents, etc. Examples: production outage affecting 20% of customers, RFC to cleanup invoices imported by error
  • Program Work: this is part of a larger body of work driven across teams in the organisation, often coordinated by a Program Manager who has flagged a team as a dependency for that work program.Examples: platform-wide localisation/internationalisation efforts that need coordination across teams or security work that all teams need to do.
  • Delivery Performance: Measurably increases the delivery speed of engineering or quality of engineering output. Often related to paying off technical debt we have accumulated over time. Delivery performance is not about product performance. Example: automating our deployment process to get code from our main branch into production faster/more frequently.
  • Functional Improvement: Deliver functional changes that our customers experience. Often a Product Manager/Owner will be heavily involved in how this type of work should be prioritised, based on research and customer input. Example: shiny new features.
  • Innovation Time: Unstructured innovation, learning, and experimentation. I made time for this in some of my previous roles by giving people half a day per week to work on anything they wanted. As long as what they are doing is visualised in our issue tracker.

♻️Iterate and Invest💰

Another observation that I would like to add is that there is often a natural ebb and flow to our work in Engineering. For example, we might spend periods delivering a lot of work in very tight iterations. Over time the assumptions we made doing this work will accumulate. While code behaves as expected, we discover that our expectations were wrong. As a result, our velocity slows, or developer happiness decreases. Then we need to switch mode from tight iterations into one significant investment effort with all our chips pushed into the middle of the table. Finally, in this investment mode, teams have to focus on a considerable cleanup effort before switching back into another cycle of sustainable product iteration.

📊 Metrics

I don't have time to go into how I see metrics fitting into the "operating system" I describe above. Still, metrics are vital, and I wanted to mention metrics in passing. At a high level, I believe the following areas are necessary to track:

  • Employee engagement and developer happiness
  • The flow of their work (e.g., lead time and cycle time/deploys)
  • The quality of their work and the impact/outcomes for users (e.g., using something like the North Star Metric Framework).
  • Bugs can be a proxy for this work, but the team's percentage of time spent on unplanned work is another way to track this.
  • The technical performance of their system via the four golden signals - latency, traffic, errors, and saturation.

Wrapping Up 🔚

This topic ended up getting longer and longer. I could keep going, but I have to respect my timebox reserved for the newsletter.

Have a great week!

Jeremy (he/him)

Don't ignore your dreams, don't work too much, say what you think, cultivate friendships, and be happy.

📌 Follow me on LinkedIn and Twitter.

❤️ Enjoy this newsletter?

Forward to a friend and let them know where they can subscribe (hint: it's here).

Anything else? Hit reply to send me feedback or say hello.