Reducing technical debt from feature flags
Read time: 8 minutes
Last edited: Jan 13, 2022
This guide provides ways to reduce and eliminate technical debt related to feature flags using LaunchDarkly. Like all debt, technical debt accumulates over time, but you can mitigate that debt over time if you put effective processes in place before you need them.
In this guide, we'll explore:
- The challenge of technical debt
- The lifecycle of a flag
- Naming conventions
- Using tags
- Code references
- Archiving and deleting flags
Just like feature flags should be a core engineering practice, so should a strategy to address technical debt.
To complete this guide, you must have the following prerequisites:
- Proficiency and understanding of creating a feature flag in LaunchDarkly
- Knowledge of your organization’s release process
You should understand these concepts before you read this guide:
Technical debt is a concept in software development that describes the implied cost of rework required in the future because of short-term, limited solutions. It is often caused by choosing a fast, limited solution now instead of using a better approach that would take longer. A common reason for this is that necessary work must be delayed to meet a deliverable or a deadline.
As this debt accumulates, it is harder to maintain the system and code, which can impact the speed of development and efficiency of your codebase in the future.
One way technical debt can accumulate is when you fail to maintain your feature flags.
The software delivery lifecycle (SDLC) is a process followed for a software project. The process describes how to develop, maintain, and modify software. The stages of the software delivery cycle are:
- Testing and integration
Flags are either temporary or permanent. A temporary flag has a limited lifespan. Once the flag has fulfilled its business purpose, remove it from the codebase. Temporary flags include flags for release management, experiments, and interoperability testing.
Permanent flags provide control for an extended time after the release of a feature. They will potentially exist for the life of a feature. Permanent flags include flags for entitlements, load shedding, custom-branding, or accessibility.
Every feature should have a flag, but if you don't regularly archive flags, you can accumulate a lot of debt.
Cluttered code is harder to maintain and test. Unnecessary code remains because nobody remembers why it existed, and there is a fear that things will break if it is removed. Failure to remove flags leads to cluttered code.
Not only do you want to remove the references to the flag in your code, but you also don’t want to send evaluation settings for flags you don’t need. When you use features like Data Export to track the impact of your rollouts, your database may be overwhelmed with unnecessary event data. You don't want to transfer and store data on flags that should have been archived six months ago.
Failure to remove flags clutters your LaunchDarkly dashboard, as well as your code. You can’t quickly find the flag you need to toggle. This may seem like a minor inconvenience, but if you need to quickly toggle a flag off, having to scroll through hundreds of flags adds time. But cluttered code and dashboards aren’t the only challenges.
You also run the risk of an old flag evaluating to a state that is invalid or undesirable. When you’re rolling out a new change such as an updated UI, it is common to keep the default version to the current UI until you have confidence in the new one. Once 100% of users have the new UI, the flag has reached the end of its lifecycle and should be archived. Failure to do this runs the risk of falling back to the undesired old UI if a flag gets turned off or an SDK failure results in using the fallback value. Speaking of fallback values, test the fallback values of permanent flags periodically, to ensure they are up to date and delivering valid states.
The LaunchDarkly dashboard provides the status of every flag and when it was last evaluated. Statuses include:
- New/Never Requested: This flag has not yet been evaluated. This status most commonly appears for newly created flags.
- Active: LaunchDarkly is currently receiving requests for the flag using your production SDK.
- Launched: All users have been receiving one variation of the flag for seven days or more.
- Inactive: The flag has not been requested for seven days or more.
To learn more about flag statuses, read The dashboard.
Do not archive flags solely because of their status. For example, consider this flag:
This flag’s status is “Never requested,” but it was added over a year ago. Maybe it was created on accident, maybe the feature never shipped, perhaps it shipped with a different flag. Whatever the reason, no one is using the flag. You can archive it.
If you don't archive flags that no one is using, they can become a form of technical debt.
Here are some processes you can follow to reduce or eliminate flag debt in your organization:
A shared naming convention for your organization's flags is an effective way to eliminate debt. Flags should have understandable, intuitive names.
For example, when the developer that created flag
FF123_dont_delete_this_72 leaves the company, the person who takes over their work cannot necessarily tell what that flag is supposed to do. The name of that flag is too obscure to easily determine if the flag is important or not, and taking time to find the flag references in the codebase, determine the results of its variations, and calculate the impact of archiving the flag all seem less urgent than other work.
If flags do not have human-readable names, they can become technical debt.
Use descriptions to add more context to the flag. Unlike flag names, you can update descriptions. They can include detailed information, such as the date the flag was last reviewed, the purpose of the flag, and more.
Descriptions are fast ways to help other account members learn what a flag does and what its impact is.
A flag should have limited scope. Having a flag that controls more than one feature action at a time can be confusing and can make it harder to troubleshoot problems.
Imagine the smallest unit of logic needed for the most responsive flag. If there are multiple parts to a feature that have to work together, you can create a main flag with other flags dependent on it.
For example, you launch a new dashboard with three widgets. To manage them, create four flags: one flag for each widget, with a dependency on a fourth flag for the main dashboard. In this scenario, if one widget causes problems, you can disable it and still serve the dashboard with the two remaining widgets.
LaunchDarkly provides the option to archive or delete a flag. The LaunchDarkly SDKs consider archived flags “gone.” When you archive a flag as opposed to deleting it, the flag's history remains in your LaunchDarkly project. If you delete it, all references to the flag, including the history, are deleted from LaunchDarkly.
Our flag archive process lets you confidently remove flags and help you reduce technical debt. When you select a flag to archive, the panel walks you through the archiving process.
To learn more, read Archiving and deleting flags.
If you do decide after archiving a flag to delete it, you may choose to restrict who can delete flags by assigning them a custom role.
Schedule regular review cycles on a monthly or quarterly basis to identify flags to archive.
During a review cycle, search for flags with Launched and Inactive statuses. Both of these status types indicate flags that may be candidates for removal.
You may also want to filter for flags
maintained by me to reduce the results to flags you own.
Here is an image of a flag filter:
For temporary flags, filter your flags by status:
- Navigate to the feature flags dashboard and click Filter.
- Choose Status from the “Add a filter to refine your search” dropdown:
- Select a status of "Launched" or "Inactive."
- Archive the flags you no longer need. Be sure to only archive temporary flags, not permanent ones.
- Repeat steps 3 and 4 for the status you did not filter by the first time:
During these review cycles, you should also review any permanent flags to determine that they are still necessary. As features change, the need for the flags associated with them can also change.
Some companies dedicate sprints to tackling technical debt. If you do this, make sure to include a review of your feature flags, too.
When you create or edit a flag, you can indicate whether or not the flag is permanent by selecting the This is a permanent flag checkbox in the flag's Settings. When someone tries to archive a permanent flag, a warning appears. This can help prevent them from being archived unnecessarily.
You can also filter flags based on whether they are temporary or permanent. This can help you find flags to archive.
When you conduct a flag review, confirm the This is a permanent flag checkbox is selected for every permanent flag.
To learn more, read Flag settings.
Tags are strings you can attach to any flag within LaunchDarkly. They help you group resources together.
You can control the spread of technical debt with tags by including a tag with a sprint designation or deploy date. When you conduct your regularly scheduled reviews, you can search for specific sprints or deploy dates.
Tags are case sensitive. Searching for Permanent and permanent will yield different results.
Each company and even each team within an organization may have their own standards for what constitutes "done" on a task or project. Done indicates the project can be removed from the list of current tasks. For example, a team may consider the code for a task to be incomplete until it has automated tests.
Done means different things for different teams, a feature may be done when it rolls out to 100% of users, or when it roles out to a specific set of users. Your definition of done should include archiving temporary flags. A feature is done when the flag is archived.
If the flag you use for a release will convert to a permanent flag, the definition of done should be when the setting on the flag changes to indicate it is permanent. You can make archiving flags part of each sprint or project end. Using this method, you do the work to archive or delete the flag when the context is fresh.
To learn more about integrating flag archiving behavior into your feature development processes, read the LaunchDarkly blog article How to use feature flags without technical debt.
Archiving a flag removes it from the flag dashboard and your app's users no longer encounter it.
Before you do this, you need to remove the flag from your codebase. Code references let you quickly find where in your source code feature flags are referenced. This simplifies the process of finding code to remove in projects and files.
To access code references:
- Navigate to the flag dashboard and find the flag you wish to remove.
- Click the flag's name to open the flag dashboard.
- Click into the "Code references" tab:
To learn more, read Code references.
Create a branch that will remove a flag when you create the flag itself. You can use the flag to toggle a feature on or off, and merge the branch in after the feature releases and its performance is consistent.
The code may change before you merge the branch, but creating it gives you somewhere to start when you're ready to clean up the code. The presence of the branch also serves as a reminder to remove the flag when it's no longer needed.
You can use the Slack app to subscribe to notifications when it’s time to remove flags from code. To learn more, read Receiving alerts when flags are ready to remove.
In this guide, you learned about:
- Challenges of technical debt
- The flag lifecycle
- Processes and features within LaunchDarkly to help control flag debt
Your 14-day trial begins as soon as you sign up. Learn to use LaunchDarkly with the app's built-in tutorial. You'll see how easy it is to manage the whole feature lifecycle from concept to launch to control.
Want to try it out? Start a trial.