Planning Software Releases
In this article I’m going to put my Product Owners’s hat on for a short while. I already wrote about what happens when we release software and how to support this with a branching model tailored for SemVer. If you have not read these articles, it might be a good idea to review them now.
Assumptions
Before we dive in, I’d like to outline a few things I take for granted in my description. However, as you will see, they are not too limiting, and maybe you will even see them as natural and obvious.
- You do not need to follow any specific methodology, but since we are going to discuss scheduling, it only makes sense to have the scope of work divided into discrete work items. Each of these items can be selected for implementation in a given planned version and worked to completion. For projects following an agile approach a work item is a story.
- You need to have a way to assign one or more planned versions to a work item. In its most rudimentary form, this may look like stories written on index cards with the version numbers penciled in, perhaps augmented by cork boards and rubber bands. Practically speaking though, these days, I would expect to find some kind of work management software, like it or not. Jira is probably the most common usual suspect in the corporate world, and it does allow multiple versions per work item as well as seeing what work items are assigned to each planned version. Jira by itself is not a requirement, use what you like.
- You will need a way to provide some estimates for the work items. How you do it is not important: ideal days, story points, etc. In the most extreme case, you can try splitting all work items making them as small as possible, and then assign to all of them the same estimate of 1 unit.
- You will be using SemVer to number versions, at least using the format. If the product you develop is a software component exposing an API, SemVer is more or less a given—the alternative is chaos. But even if your product is a stand-alone application with no downstream consumers, you still can use SemVer, perhaps with slightly adjusted meaning behind minor versions.
While not exactly assumptions, the following are good to have to help the process work smoothly.
- It is important to have open two-way communication with the client, the party that commissioned the product. You will need to show progress and seek feedback by giving frequent periodic product demos. You will need to refine the planned scope of the releases to hit the predefined dates. It works much better when you can talk to the client instead of taking directives from your superiors in the form of “the client wants…”
- In order to timebox the certification of a version to be a release it is essential to have the vast majority of your tests automated. Manual testing creates too much uncertainty at the most critical junction.
Greenfield Phase
Everything has a beginning. When you start developing a new product, you have no choice but to plan what will be included in the first release. There are a couple of competing forces at play here.
Time
The amount of funding and the team’s size determine the maximum stretch of time you can use to get to the first release. The client may have additional time constraints, such as regulatory requirements, scheduled product presentations, trade shows, etc. The date of the release, more often than not, is carved in stone. In the projects I led, the timespan to the first release ranged from nine months to two years.
You will need to timebox the work required from the first version, 1.0.0, to the version that is ultimately certified as a release. In my practice, I could never release 1.0.0 and had to produce between four and six subsequent patch versions in preparation of the release. Based on the list of items I need to check off during the certification and the amount of organizational friction, my time-box is normally set to six weeks. Your mileage will certainly vary.
Then you count backwards from the set release date the number of days in the time-box. This will give you the date when you need to produce your version 1.0.0—the first feature-complete version of the product.
Scope
On the other hand, what work items you select to be implemented in the first release will determine the ultimate success of the product as well as future investments in its development. You may have heard about things like Minimal Viable Product that help to make this cut.
However, when you just start, don’t sweat too much over the work item selection. Try to keep them stack-ranked based on the client’s wishes and make the first rough cut for version 1.0.0. Don’t make any predictions or promises at this point—you have no data.
Often at this point you’ll hear: “Why are we wasting time? I want it all done by the deadline.” Don’t get distracted by this. You don’t know what “it” means and neither do they. Stay the course. Split the work items as finely as possible. Get the data.
Time Estimate
We need a quick data-driven way to check if the scope we have can be done in the available time. To get the data you need to start working on the highest priority work items in your stack-ranked list and complete a handful of them, let’s say ten.
At this point you know how many working days it took to complete the work items and what is the sum of the estimates assigned to them. This will allow you to calculate how long it takes to complete one unit of estimate. For example, we completed 10 stories in 25 working days, we chose not to do estimates for each individual story, but rather assign one point to each of them. Then it “takes” 2.5 working days to complete one point of scope.
Next, add 10% to this number and subtract 10% from this number. This will be our pessimistic and optimistic cases. In the example above these are 2.75 working days and 2.25 working days correspondingly.
Finally, multiply these numbers by the sum of remaining estimates in version 1.0.0 and plot the dates on the calendar. This will give you three dates, the cone of uncertainty with the optimistic, pessimistic, and likely predictions. Let’s say that we started working on the version on April 1, 2025, and the version had the scope of 173 stories. Then after 25 working days, on May 6, 2025, we would have 163 stories left in the scope and the predictions would look like this (the calculation assumes the US federal holidays schedule).
| Prediction | Duration, days | Date |
|---|---|---|
| Optimistic | 367 | October 30, 2026 |
| Likely | 408 | January 4, 2027 |
| Pessimistic | 448 | March 3, 2027 |
This probably looks quite horrific and the cone of uncertainty is pretty wide. How you react to this really depends on where the scheduled date for version 1.0.0 lies. If it happens to be after the pessimistic date, you may have nothing to worry about. Except:
- this is the initial calculation, and the data set is very small; expect the predictions to become worse in the subsequent calculations when your data set grows;
- for every work item in the initial set I expect a few more to be added as we understand the problem better, and this understanding starts contributing to the scope.
Moreover, for all the years in my career, I’ve never been in the situation when the prediction was favorable. People are ambitious and overly optimistic creatures and every time the first version deadline ended up way before the optimistic date for me. Every damn time.
You will need to run these calculations periodically, at least weekly. The tools you use may have a way to automate this reporting. For example, Jira comes with Version Report, which predicts the dates using exactly the algorithm described above. The algorithm can probably be adjusted in some way to make it more precise. I have to say though, once the data accumulates and the scope gets burned down, the cone of uncertainty shrinks, and the predictions become deadly accurate.
Hard Decisions
Now that you have the data you must share it with the client. They are not going to like it, but this is your earliest, your best chance to course-correct. Don’t waste it.
Basically, it is your job as the Product Owner to adjust the scope for the first release in such a way that it fits the calculated predictions with some room to spare. The estimates will become worse over time due to the factors I already mentioned. At the same time, the client needs to have a strong reason to release the version with the reduced scope. I’m not going to give any advice how to make it happen, this is not the focus of this article. I refer you to User Story Mapping by Jeff Patton for ideas.
What I can say is this:
- Don’t use the word “hope”. Hope is not a strategy. Use data. Promise to the client frequent periodic updates of the predicted dates based on the data you collect.
- Build trust with your client by demoing steady progress in the product development. Do not say “no” to the changes resulting from the demos, yet, make sure the client understands the impact of the changes to the schedule.
- Don’t agree to add more developers to the team. This looks like an easy fix to the folks not involved in software development, and almost certainly, you are going to hear this suggestion. Fred Brooks in his The Mythical Man-Month has shown how this would end, you don’t need to relive this experience.
- Do not discuss any internal development activities with the client. People who like sausages must not see how they are made. Once you mention unit testing to the client, expect a suggestion to stop doing it to go faster. Happens every time.
- Refuse to discuss any code quality compromises. Such compromises will derail the steady progress you’re making and will significantly endanger the schedule.
- Be thoughtful about how you define scope, aim for the smallest increments in the functionality. For example, “I want to be able to search” does not mean “I want to have progressive search with results showing up as I type the query”. This is certainly an extra and could be done later, in the next release.
- Speaking of the next release. The fact that you use SemVer and can do minor releases gives you a trump card in the scope conversation. You can say: “OK, what about we cut this from the first release, but you’re going to have this feature within three weeks after the release.” Sometimes it does magic.
To summarize: scope is the only variable you can play with. Be creative.
Refining
As you progress with the development of the first version, a few things will happen. Your estimates will become more accurate and more reliable. You will learn to trust them. If you play it right, you and your client will learn to trust each other. They will learn to trust the estimates too.
The more code you write, the more you learn, and as you learn, the scope of the first version will increase due to various refining work items added to it. Maybe that progressive search is the hard requirement after all, the killer differentiator from other products on the market. Things that were rarely discussed in the beginning, like audit trail, data integrity checks and similar things come up. If you already have a legacy system, the data migration will become a hot topic and so on.
At the same time, some things that looked essential in the beginning somehow start losing their luster. Some will make the full progression from “must haves” to “may be nice” to “why on Earth did we include it”. Use such opportunities to reduce the scope.
You will need to recheck your predictions frequently and make adjustments to the scope to hit the date. Somehow I relate this experience to trying to land a huge airliner on a tiny landing strip.
Alas, I don’t want to hide the fact that sometimes people cannot handle the truth. Faced with inconvenient data and the question whether it’s going to be your job on the line or theirs, it will always be yours. If such situation develops, they will apply pressure first to you directly, then through your chain of command. Try not to get fired. You know your data is right and that the goal is unachievable within the timeframe. Again, I don’t want to give any concrete advice, remember: signing a blank check will only delay the inevitable.
Endgame
But enough doom and gloom. Let’s say you succeeded. You managed to land that airliner. Now you have your first version tagged and published. If you were diligent with the development process, the following points are also true:
- you have a fully automated suite of functional tests that runs on every build and the produced version just passed it;
- you’ve been doing exploratory testing on the deployed code and addressed most if not all findings;
- this is not the first time your client sees the product, you’ve been doing frequent demos to the client and allowed the client to play with the deployed snapshots;
- you did a few rounds of stress testing for your product, evaluating how it performs under a realistic load;
- you did some preliminary scans for security and compliance issues;
- if applicable, you can automatically deploy the code to any target environment;
- you started the certification paperwork in preparations for the first release, part of the paperwork includes the release notes for the version;
- you have
releng/1andreleng/1.0branches created and ready to accept changes.
From this point you have the time-boxed period to complete the certification of the version for the release and production use. Given the extensive list above, there should be no huge surprises and the time-boxing should certainly be possible.
Any issue with the product found during this time is documented as a bug first. Next, you must have an answer for the question: “Can this be addressed in version 1.1.0 or later?” If the answer is “no, it needs to be fixed in the first release”, it means that the certification of version 1.0.0 just failed, and we need to produce 1.0.1.
The bug then is scheduled to be fixed in 1.0.1, 1.1.0, and 2.0.0. This notation highlights that we want to avoid the regression of the bug, and that regression avoidance merges need to be performed in the respective branches. It also serves as a reminder for anyone who sees the work item that any change done in 1.0.1 by definition is also present in 1.1.0 and 2.0.0. Work management tools that can generate release notes, such as Jira, will include the corresponding work item in each version.
Bugs for which the answer is “yes”, are scheduled for 1.1.0 and 2.0.0. Again, this is done to signify that anything done in 1.1.0 is also present in 2.0.0.
Once all bugs scheduled for 1.0.1 are fixed, this version is tagged and published, and the certification cycle repeats itself. The last produced version gets certified. As I already mentioned, it is likely to take several attempts in the form of patch versions, and you need to manage the time to stay inside the time box.
Opportunistic Development
Once you produce version 1.0.0 it is likely that you do not need the whole team to address the issues coming from the certification process. People not directly involved in working on these issues can move to work on the future releases.
I’ve seen a desire, however, to start working on 2.0.0 or 3.0.0 even before 1.0.0 is feature-complete. Personally I see this type of activity as a waste production, WIP in its purest form. I’d like to understand better why some feel the urge to place the developers to work on the next major version while the current one still needs work. Bad planning? Perhaps.
Release Notes
I’d like to say a few words about the release notes I mentioned earlier. While many tools can produce them from the version information in the work items, I like my own format for the notes.
In addition to the literary part describing the principal novelties of the release and other useful information, I like having a complete list of all work items in the version, grouped in four lists.
The first list includes all new features in the version. The second list has all the bugs discovered in the version and fixed in the same version. Normally, these bugs come from exploratory testing or the fixes come as part of regression avoidance merges from lower versions. The third list contains the bugs found in lower versions but fixed in the current one. Finally, the fourth list contains bugs we know are present in the current version. The fixes for such bugs are done in the higher versions.
In order to create such lists, one needs to maintain in each bug the list of the versions it affects. Basically, when you produce a new version, you need to check and update every open bug. This is overhead, and it can be minimized by prioritizing bug fixes over new features. Your users will also thank you for that.
Brownfield Phase
Greenfield is fun, especially in the beginning. But now you have a released product on your hands, which needs to be maintained. And this brings new questions and challenges. For example, version 1.1.0 will almost certainly happen because of the trump cards you had to play to keep 1.0.0 on schedule. But do you have enough ideas and economic interest to justify 2.0.0? Let’s hope yes.
Release Schedule
For the first release we probably took our time. For the subsequent major releases we don’t need to wait that long. In fact, the faster you can bring your ideas to the market, the better economic outcome you can expect. On the flip side, important changes to the product may take significant time. As everything in life, it is a balancing act, a trade-off.
In the corporate environment I come from, we tried to release a major version every quarter. I would say this is on the shorter side, because on some occasions our major versions felt a bit lightweight. Maybe twice a year or annually will work better for you. Your client will certainly have an opinion about it too. Personally, I prefer to have a regular schedule over an ad hoc approach.
Because of SemVer, you have an option to fill the time between two major releases with minor ones. In true SemVer, work scheduled for minor releases must not break the API. Either way, such items tend to be less involved and therefore less risky and quicker to implement. If we talk about regular schedule, I would set minor releases a few weeks apart, sufficient to implement and certify a few smaller changes. The certification time box can be significantly shorter for minor releases due to their limited nature. They are highly likely to get certified on the first pass.
Finally, it is worth mentioning that because you now have a released version, having critical production bugs is a possibility. In SemVer the vehicle to address them is patch versions. These can be scheduled as needed and have a few days turnaround time, from the bug report to the patch release. It is not uncommon to have just one bug fix per patch version.
Work Item Scheduling
Before any work item can be worked on, it must be scheduled to a version. This determines on what long-lived branch the change will originate. It can be scheduled for the next major release. This can work for any work item, no special conditions need to be met. If a work item introduces a backward compatible change to the API (or no API change), it can also be scheduled for the next minor release. Finally, if a work item is a fix for a critical bug, that is, it brings an incorrect behavior in accordance to the specification, it can be scheduled for the appropriate patch versions.
It is worth repeating, that due to regression avoidance merges anything scheduled for a patch release will get propagated to every higher branch, and therefore will be present in any higher version of the product. For example, any work item scheduled for 1.0.4 will also be present in 1.1.1, 1.2.0 and 2.0.0. Likewise, any item scheduled for the next minor release will also be present in every higher version too. For example, anything done in 1.2.0 will also be present in 2.0.0. We choose to state all target version explicitly on the work items as a reminder of this fact.
We generally keep the list of the work items stack-ranked and select items for implementation from the top of the list. Scheduling work items to versions affects the stack-ranking. SemVer defines how version numbers are ordered. Using this order we determine the lowest version number from the versions listed on each work item. Let’s call it the target version. Then the stack-ranking must satisfy the following rules.
- Items without any version assigned are always ranked lower than items with a version.
- Items with lower target versions are ranked higher than items with higher target versions.
If you think about it, it makes sense, because we expect version 1.0.4 to be released before 1.1.1, and 1.2.0 before 2.0.0. And even if we decide to cancel some release, like 1.3.0, for whatever reason, changes included in it will still be present in 2.0.2, 2.1.0 and 3.0.0. Please see Figure 2 above.
Branch Selection
To select the correct long-lived branch for the work, one needs to inspect the version assigned to the work item. First, determine the target version—X.Y.Z. Then select the branch according to the following rules applied in the order they are listed.
- Branch
releng/X.Yexists - Use this branch.
Zis zero and branchreleng/Xexists- Use this branch.
- Both
YandZare zero - Use
master.
Check the version number in the branch, it must be X.Y.Z-SNAPSHOT. Any different version found as well as a failure to locate the branch indicate work scheduled to unsupported version or some discrepancy between your version control and work management systems. Investigate and correct.
For example, a work item has 3.0.0, 2.7.0, 2.6.3, 1.4.0, 1.3.11 versions assigned to it. The target version is 1.3.11, the implementation branch will be releng/1.3. When checking, it must show 1.3.11-SNAPSHOT version number.
Time Estimates
While you can perform the same time estimates as for the first major version on major and minor versions in brownfield phase, it certainly makes no sense to do it for patch versions. Patch versions tend to include just a handful of work items in them, often just one, so there is no statistical significance in such reports.
Even for minor versions with the work timespan of a few weeks you may not have enough data points for such reports to be useful. Use your judgment.
Conclusion
Here are the key ideas from the article.
- I said the methodology is not important, but who am I kidding? Small work items, estimates and data-driven predictions, automated tests, feedback loops, open interactions with the client… you certainly recognize these ideas.
- In the greenfield phase your main goal is to hit the release date while producing enough value in the first release to be viable. The product development can only continue if your client feels like investing more money into the product.
- Using SemVer gives you great flexibility in how to schedule your work to software versions in the brownfield phase. You should give the highest priority to critical bugs and use minor releases as a vehicle to deliver small backward compatible changes to the market faster.
- It makes sense to work with the client to establish a regular release schedule that optimizes the delivery of the value to the market.