Roadmap from Monolith to Services

Create a Roadmap

Problem and Solution Overview

This recipe just states how to execute a solution. Read our Legacy Newsletter blog post: DevOps #3 – Roadmap to Escape the Monolith to understand the specific problem we are solving and the solution approach.

This recipe helps you define a technical roadmap to free your team from the monolith.

  1. Align on Goals, Obstacles, and Sequence
  2. Agree on Phases
  3. Use a Variable-Scope Experiment
  4. Identify Visible Work for Phase 1
  5. Agree on Experiment Budget
  6. Agree How to Predict Completion Dates as You Go
  7. Celebrate that you now have a flexible roadmap that can handle change!

Align on Goals, Obstacles, and Sequence

This project is going to take a while. There will be significant efforts – some of which contribute to product features and some of which do not. Team success in the difficult moments relies on stakeholder alignment.

We need to align the developers, the product owners, and management. The essential goal is to align different roles across the organization. Examples include product changers, customer representation, budget owners, and performance review owners.

  • Development roles will need to
    • Choose to do the right thing even when there is a faster way.
    • Challenge themselves to learn new ways of working.
    • Predict the business value of steps towards escaping the monolith, then demonstrate that value.
    • Stop believing that “product owners and managers won’t let me do the right thing” and accept complete responsibility for predicting a roadmap to success, then executing and sharing variations from plan.
  • Customer representative roles will need to
    • Allocate a portion of the feature budget towards escaping the monolith.
    • Defend that decision to others, even when they do not have an intrinsic feel for the benefits.
    • Predict the difference in customer retention / revenue resulting from this project, then take responsibility for those differences – and any unplanned variations.
  • Management roles will need to
    • Defend to the rest of the organization why escaping the monolith is more valuable than the normal expected work, even when normal work clearly accrues value to the organization and escaping the monolith appears to accrue value only to the team.
    • Defend the contributions of employees at annual review time, even when those contributions are not traditional.
    • Budget time and money to support intensive learning by the team.

This project will require moments of courage from each role. We need them all to equally understand the benefits and risks, and then to personally agree when to escape the monolith.

Goals and Benefits

  1. Get together at least one representative of each role.
    • Also include at least one person who can speak to each value column. This may require more people from your wider project community.
  2. Fill in the following table using specifics for your team and company.
    • Use actual numbers where possible.
    • Make sure you fill in every cell.
    • Include just the highest impact 1-3 measures for each cell.
  3. Add any additional columns that matter for your project community.
    • Think through the audiences for your status emails. Who cares about your project and why?
    • Include additional columns as needed and go find audience members to help fill in the value measures.
GoalTeam ValueOrg ValueCustomer ValueManagement Value
Edit Indep.
Verify Intent Indep.
Compile Indep.
Integrate Indep.
Verify Interactions Indep.

For example, if your team can compile independently then:

  • Other teams in the org see their compile times reduce by X%.
  • Other teams are no longer impacted by bugs that block your build or that you find and fix before release.
  • Managers see that the number of features that require scheduling sequenced development among dependent teams drops by Y%.

As you fill out value columns, look for values that your team can complete without the audience needing to take actions.

Obstacles and Cost Impacts

Attaining each goal will have an investment cost. Some progress will be made as a normal part of doing stories. However, finishing the goal will require additional investment.

This is the general dependency map for technical solutions and obstacles. We will create a roadmap that starts at the bottom of the iceberg and allows us to finish each technical solution and start accruing value as early as possible.

There are usually thousands of instances of each obstacle, and those instances are easy to identify and count. We must complete every instance before we can achieve the technical solution that depends on them. Therefore we will measure progress by counting instances of the obstacles.

However, we can usually start implementing solution in parallel to addressing the obstacles. The solution will gain usefulness as we incrementally extend it. That allows us to determine the value of the project as we go. We do this by assessing the utility of the technical solution.

Agree on Phases

Our roadmap will complete in 3 phases.

  1. From Code to Components — accomplishes the first two goals of Edit Independently and Verify Intent Independently
  2. From Components to Libraries — accomplishes the third goal of Compile Independently
  3. From Libraries to Integrations — accomplishes the fourth and fifth goals of Integrate Independently and Verify Interactions Independently

Each of these phases will be qualitatively different.

  • We will measure progress differently
  • We will perform different kinds of work
  • We will need different skills
  • We will make different kinds of investments and gain different results

As such, we will manage each phase as its own project.

Phase 1: Code to Components

Goals attained: Edit Independently & Verify Intent Independently

Timing: all at once. The phase to extracts all the code your team modifies. This will create all components at once.

Actions: break dependencies, gather scattered code, create components, unit test the core of each component.

Sequence:

  1. Extract code to find components, testing as you go.
  2. Gather scattered code to fill out components, testing as you go.

Skills needed: disciplined refactoring; insight loop; approval testing; and dependency breaking recipes used to enable unit tests, break up shared classes, and isolate code that depends on shared classes.

Investment needed within each story: add 30% to cost, used to break dependencies, extract code into a component, and add missing unit tests.

Additional investment needed: gain skills, gather scattered code that is not impacted by current stories, break up integration tests that execute extracted code.

Measuring progress: count lines of code touched by this team in last 2 years which is not yet in one of the team’s components. Also count the number of component-external tests that execute any code in the component. Drive both of these to 0 at the same time.

Measuring value: use the first 2 rows of your value table. Identify how to measure that at least weekly and do so.

Phase 2: Component to Library

Goals attained: Compile Independently

Timing: one at a time. Finish each component before you start the next and do the most important first.

Actions: create APIs, identify abstractions, provide extension points, reduce chattiness across component boundary, separate build pipeline, modify product build to consume binary instead of code.

Sequence:

  1. Create basic API.
  2. Convert to binary library.
  3. Resolve API problems (chattiness and forward compatibility issues)

Skills needed: disciplined refactoring, API design, build management, package management.

Investment needed within each story: none.

Additional investment needed: gain skills, flat cost to convert each component from source interaction to binary integration, additional time to clean up the APIs.

Measuring progress: first count the number of dependents that use the component as source. Drive that to zero. Then count the number of calls across the library boundary. Reduce that until it is manageable. Then examine the API for future compatibility problems, security problems, or missing concepts. Create bugs and stories for these, then complete them all.

Measuring value: use the third row of your value table. Identify how to measure that at least weekly and do so.

Phase 3: Library to Integrations

Goals attained: Integrate Independently & Verify Interactions Independently

Timing: one at a time. Finish each component before you start the next and do the most important first. You can even perform this phase on some components while others have not yet started phase 2.

Actions: isolate complexity with ports and adapters, create and ship client libraries, create port tests.

Sequence:

  1. Use ports to simplify the library’s view of the product.
  2. Use ports to simplify the product’s view of the library.
  3. Create a client lib to contain the simplification of the library.
  4. Write port tests to verify interactions.

Skills needed: disciplined refactoring, ports and adapters architecture, port unit+platform test pattern.

Investment needed within each story: add 10% to simplify the library’s view of the product, as it impacts this story.

Additional investment needed: gain skills, time to build client library, time to build port tests, political support to add specific tests into other teams’ builds.

Measuring progress: count the interactions between product and library that do not go through one of the port classes. Drive that to 0. Create stories for port tests and complete them.

Measuring value: use the last 2 rows of your value table. Identify how to measure that at least weekly and do so.

Use a Variable-Scope Experiment

Each phase significantly changes the codebase into a form that allows the next phase to start. Therefore we cannot predict the number of elements we will have to complete in later phases until we see how the earlier phases changed the code.

However, the reality is a contradiction. While we can’t predict the work, it is critical to predict our outcomes. This allows others to understand the investment and choose to fund the project. We also need to know when the project is going poorly so we can make a change.

We can resolve this conflict with a Variable-Scope Experiment.

A Variable-Scope Experiment follows the process outlined below. At this time we just need to get everyone to agree that we will use this process. We do not need to establish a budget or scope yet.

  1. Identify an experiment budget.
    • You must be willing to risk losing this budget and gaining nothing. The experiment might fail.
    • The budget should be represented as a percentage of the team’s effort each week for a fixed period of time. This budget is beyond any impact to stories.
  2. Identify an initial scope direction.
    • This must include at least one starting point.
    • This should include several options for work that we may do. It may include contradictions or alternatives.
    • The direction is allowed to change; we may create new stories and throw out these.
    • There is no commitment to complete any of it.
  3. Identify a progress measure.
    • This same measure should work across most or all scope directions. We are measuring progress towards the goal, not completion of actions.
    • This should be automatically measurable. Counting instances of some code construct is a good example.
    • Measure this daily. Chart the results to share with stakeholders.
    • Also measure the delta per commit. Use that as a gateway to prevent massive regression.
  4. Identify an experiment cycle length.
    • This should be long enough that you expect to see real change in the progress measure within each cycle.
    • It should be short enough to get many cycles within the experiment budget.
    • Define a goal at the beginning of the cycle. State how much you expect the current scope direction to alter the progress measure.
    • Plan a review at the end of each cycle. Adjust scope direction if the cycle did not make sufficient progress.
  5. Assess the entire experiment once it expends its budget. Decide whether to fund an additional experiment for the next set of work. The new experiment will have a different budget.

Identify Visible Work for Phase 1 (Code to Components)

Measuring Progress

The majority of our work in Phase 1 will be to address the obstacle of scattered code (measurement #1). Gathering each chunk of scattered code will require breaking dependencies, so we can consider the obstacle of dependencies to be part of the gathering process. We will also test each chunk as we import it, so creating core unit tests is accounted for by measuring the obstacle of scattering.

The other large chunk of work is to break apart existing tests (measurement #2). We have to measure that separately. Each time we import scattered code, we will likely increase the number of external tests that execute component code. We will then do work to bring that back down to 0.

Unseen Work

The following are too difficult to measure directly, but they tend to be consistent over time. We will model them as unseen work.

  • Breaking apart external tests so they don’t execute component code.
  • Extracting code near a known-scattered line that really should move with it.
  • Breaking exceptionally difficult dependencies.
  • Other things your situation will throw at you.

Additionally, new visible work will arrive at a regular rate.

  • Some stories will require the team to edit non-component code that is not already a known scattering, thus increasing the number of known-scattered lines for us to extract.
  • Some stories will require the team to edit a known scattering. The team will import the scattering as part of the story work, which will not count against the experiment budget for importing other scatterings.

Identifying Components

External stakeholders may want to know the team’s components before you start working. If so, spend a few days gathering 20 to 50 scattered lines. These will cluster and give you a good initial set of components. It will usually take less time to perform these gatherings than it would to predict and argue over the “logical” components for your team to own.

Assessing Interaction with Planned Stories

Initially, guess that each story will become about 30% more expensive. Some stories will require gathering many sets of scattered code. Some will not. It’ll average out to some ratio of story size – larger stories will change more code and generally require importing more code.

Three weeks into the experiment, update your story costing based on actual results.

Agree on Budget

Your budget needs to include:

  • The percentage of velocity you will reserve for the project, before taking in feature work.
  • The duration for which you will make that reservation.
  • A total amount that you are comfortable risking – the experiment might fail, and that has to be safe.

Your budget must also:

  • Take into account that the project may also slow down feature work stories by adding scope to them.
  • Be agreed upon by the customer representatives, the developers, and the people assessing team performance.

Argue amongst yourselves until you find a good number. One common answer is 30% for one quarter.

Measuring Budget Utilization

If left unobserved, most teams will beg for this budget, say they will use it, not actually use it, and then blame other roles for why the budget was unused. That’s not poor behavior, it’s inertia. Groups of people will tend to follow their old behavior – and this budget is simply new behavior.

Therefore, it is critical to make budget utilization visible. Track efforts related to this project in the same way as you track feature work (such as stories on a board). Mark these stories differently so you can track the amount of your velocity or time you spend on regular feature stories and on stories for this project. Calculate that ratio for each day, week, experiment cycle, and other useful time period. Display those ratios publicly.

Managers and PMs should regularly review the actual spending ratio with the developers. Usually, developers will underspend on this budget. Managers and PMs need to hold them accountable for that behavior and ask them to spend according to the budget. Yes, that means PMs will be asking teams to stop over-working on features. That’s why it is critical for the team to have filled out the Customer Value column in the value table.

Agree How to Predict Completion Dates as You Go

  1. Measure your progress measure daily. This will decrease as we address obstacles and increase as stories help us find more obstacles.
  2. Assuming budget is consistent, draw 3 trendlines:
    one at 2/3 the current rate, one at the current rate, and one at 1.5x the current rate.
    • If budget is not consistent, then things will get complicated because budget impacts obstacle fix rate but not the rate at which we find new obstacles.
    • Use your judgment to guess a most-likely total rate. Use this for what-if scenarios but not for date planning.
    • Measure the actual rate for at least three weeks after any change before updating your predictions.
  3. Add your target to the graph. This will often be zero, but differs per phase.
    • Your target may even be moving. If so, measure its historical movement and create three trendlines for it to account for uncertainty.
  4. The trendline intercepts with your target give you your 5%, 50%, and 95% dates.
    • These dates represent the probability that you will complete sometime before that date.
    • if someone wants to estimate a different probability, say 80%, they can approximate an angle between the nearest two trendlines. They can then draw it down to get a new date.
    • Always describe these as the N% dates; never as the projected completion date. In particular, if asked to give only one date, then ask what success percentage they want and say the N% probability date is X.

You do not need to account for the impact that stories will have on your completion dates. The progress measure will automatically include all effects, as long as your behavior remains consistent.

Showing Value

Different things will be valuable to different teams and companies. Therefore you will have to establish your own mechanism for measuring value. However, keep the following guidelines in mind.

  • Measure each value measurement at least weekly.
  • Send an email each week that shows the value progression.
    • Use a chart so people can see the historical value trend as well as this week’s result.
    • Use one chart per measure.
    • Send a different email to each stakeholder role, with just the value from their perspective.
    • CC your direct and skip-level managers on each email so they can see the overall picture and participate in the ensuing discussion.
  • Provide an always-active dashboard that includes full project telemetry.
    • Show all the value charts. Allow drill-down if it makes sense for that measure.
    • Show the spending ratios as compared to plan. A bar chart across history is good for this.
    • Show a chart of the progress measure over time. A line chart works well. Include your target and trendlines on this chart. Label the percentages for each of your 3 dates.
    • Link to the dashboard from your email.

Celebrate Your Flexible Roadmap

There is no plan worth the space it takes if it can’t handle change.

We have all been victims of the changeless roadmaps – the more friendly word for a rigid waterfall experience.

That is not this roadmap.

While our technical newsletter does not explicitly bring in Agile practices, we implicitly practice them constantly. The same is present for our roadmap.

The secret to keeping the roadmap flexible to consistently do the following:

  1. Communicate in terms of the progress chart and impact charts.
  2. Do not communicate what actions you are doing that keep those charts moving.

The only exception to this is if you took action but it didn’t move a chart. It is valuable to acknowledge that the action impacting that chart failed and you’re trying something else.

And importantly, take the time to celebrate even having a flexible roadmap. After all, it’s a light at the end of the monolith tunnel!