TL;DR: Feature flags allow teams to control when and for whom application functionality is enabled, independently of code deployment. They support gradual rollouts, experimentation, and rapid feature disablement. Similar configuration switches can control infrastructure provisioning, although they operate at a different layer.
What Are Feature Flags?
Imagine deploying a new checkout feature to production while keeping it disabled for users. The code is already deployed, but the functionality remains hidden until the team decides to enable it.
This is the basic idea behind feature flags, also known as feature toggles or feature switches.
A feature flag is a software development technique that allows an application to enable or disable specific functionality through configuration or a flag-management mechanism. Instead of requiring a new deployment every time a feature’s availability changes, developers can control its behavior at runtime, provided the application supports dynamic flag evaluation.
A feature flag typically works through a conditional statement in the application code. The application evaluates the flag and determines whether a particular feature should execute.
For example:
if feature_flags["new_checkout"]:
show_new_checkout()
else:
show_existing_checkout()
The flag can be a simple Boolean value, or it can be evaluated according to user identity, group membership, geographic region, percentage-based allocation, or other conditions.
The key idea is to separate deployment, which makes code available in an environment, from release, which makes functionality available to its intended users.
Key Benefits
1. Decoupling Deployment from Release
Teams can merge and deploy unfinished or inactive functionality without exposing it to users. This supports smaller, more frequent deployments and reduces the pressure associated with releasing a large collection of changes simultaneously.
2. Controlled Rollouts
A new feature can be exposed gradually, starting with internal users or a small percentage of eligible users. Teams can observe error rates, latency, and other operational signals before expanding access.
For example, a new checkout flow could initially be available to 5% of eligible users, then increase to 25%, 50%, and eventually 100% if the results remain acceptable.
Percentage-based rollout requires an implementation that consistently determines which users receive the feature. A percentage value alone does not implement this behavior.
3. A/B Testing and Experimentation
Feature flags can expose different implementations to different user groups. Teams can compare outcomes such as conversion rates, engagement, or task completion to evaluate the impact of a change.
Meaningful experiments require appropriate assignment methods, measurement, and controls to avoid drawing conclusions from misleading results.
4. Rapid Feature Disablement
If a newly released feature causes errors or unexpected resource consumption, a team may be able to disable it without rolling back the entire application deployment.
This acts as a feature-level kill switch. Its effectiveness depends on how quickly the application receives and evaluates the updated flag, and whether the affected functionality can be safely disabled.
5. Safer Development and Testing
Teams can deploy code behind a disabled flag and enable it for developers, testers, or selected customers. This allows testing against production-like environments without making the functionality generally available.
Common Use Cases
Canary Releases and Progressive Delivery
A team can expose a new application feature to a limited group of users while monitoring its behavior. Feature flags can complement canary deployments, traffic shifting, and automated rollback.
These mechanisms have different responsibilities: feature flags control functionality, traffic management controls request routing, and deployment strategies control how application versions are introduced.
Beta Programs
An application can make experimental functionality available only to selected accounts or users. Access can be expanded as testing progresses and feedback is collected.
Operational Controls
A resource-intensive feature, such as a recommendation engine or report-generation service, can be disabled temporarily during periods of unusually high demand.
This can reduce pressure on dependent services, provided the application has an acceptable fallback behavior.
Gradual Migration
When replacing an existing implementation, a team can use a flag to switch between the old and new code paths. The team can validate the replacement before removing the original implementation.
This is useful for application migrations, API transitions, and changes to backend integrations.
Feature Flags in Helm
Helm provides a way to package and configure Kubernetes applications using charts and values files. A chart can expose configuration parameters that control application features or determine which Kubernetes resources are created.
For example, a chart’s values.yaml could contain:
features:
enableNewCheckout: false
rolloutPercentage: 10
The first value controls whether the new checkout feature is enabled. The second provides a rollout percentage for the application to consume, assuming the application implements percentage-based evaluation.
Passing Configuration to an Application
In templates/deployment.yaml, Helm can inject these values into the container as environment variables:
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 2
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
spec:
containers:
- name: api
image: payment-api:v2.1
env:
- name: FEATURE_NEW_CHECKOUT
value: {{ .Values.features.enableNewCheckout | quote }}
- name: ROLLOUT_PERCENTAGE
value: {{ .Values.features.rolloutPercentage | quote }}
The application must read these environment variables and implement the corresponding behavior. Helm does not automatically create feature-flag logic inside the application.
To override the default setting during installation, use:
helm install payment-app ./my-chart \
--set features.enableNewCheckout=true
For an existing release, use helm upgrade with the desired values. If the rendered environment variables change, Kubernetes will typically roll out new Pods through the Deployment controller.
This is a configuration-driven approach to feature control. Because the settings are supplied through the Deployment, changing them is generally a deployment operation rather than an independent runtime flag update.
Conditional Resource Creation
Helm can also conditionally create Kubernetes resources based on chart values.
For example, the following template creates a ConfigMap only when the new checkout configuration is enabled:
{{- if .Values.features.enableNewCheckout }}
apiVersion: v1
kind: ConfigMap
metadata:
name: new-checkout-config
data:
experiment_mode: "active"
{{- end }}
When the value is false, Helm omits this resource from the rendered manifests.
This is useful when an optional component or supporting configuration should exist only when a particular capability is enabled. However, conditional resource creation operates at the infrastructure configuration layer; it is not equivalent to toggling application functionality at runtime.
Feature Flags in Kubernetes
Kubernetes ConfigMaps can store non-sensitive application configuration, including feature-flag values.
For example, a ConfigMap might contain:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-feature-flags
data:
ENABLE_NEW_CHECKOUT: "false"
ROLLOUT_PERCENTAGE: "10"
A Deployment can expose the configuration to its containers:
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 2
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
spec:
containers:
- name: api
image: payment-api:v2.1
env:
- name: FEATURE_NEW_CHECKOUT
valueFrom:
configMapKeyRef:
name: app-feature-flags
key: ENABLE_NEW_CHECKOUT
The application reads FEATURE_NEW_CHECKOUT and determines whether the new checkout functionality should execute.
There is an important operational detail here: updating a ConfigMap does not automatically update environment variables inside existing containers. The Pods generally need to be restarted or replaced to receive the new environment-variable values.
ConfigMaps mounted as volumes can receive updates eventually, but the application must reread the updated files to use the new values. Applications that require immediate, centralized flag changes may benefit from a dedicated feature-flag service or another dynamic configuration mechanism.
ConfigMaps should not store secrets such as API keys or passwords.
Infrastructure as Code: Terraform
The same general idea of a conditional switch appears in Infrastructure as Code (IaC). However, a Terraform variable that controls resource creation is better described as an infrastructure provisioning toggle than an application feature flag.
For example, a team may want to enable advanced logging only in selected environments.
variable "enable_advanced_logging" {
description = "Whether to create the advanced logging metric filter."
type = bool
default = false
}
resource "aws_cloudwatch_log_metric_filter" "error_filter" {
count = var.enable_advanced_logging ? 1 : 0
name = "ApplicationErrorFilter"
pattern = "ERROR"
log_group_name = aws_cloudwatch_log_group.app.name
metric_transformation {
name = "ErrorCount"
namespace = "CustomMetrics"
value = "1"
}
}
When enable_advanced_logging is true, Terraform plans to create the metric filter. When it is false, Terraform plans to omit that resource.
The setting can be supplied through a variable file or overridden on the command line:
terraform apply \
-var="enable_advanced_logging=true"
Terraform evaluates the variable when planning the infrastructure changes. Applying the resulting plan changes the managed infrastructure; it does not dynamically toggle functionality inside an already-running application.
Resource creation and destruction must also be considered carefully. Disabling a provisioning toggle can result in Terraform proposing to destroy the resource it previously managed. Teams should review the plan and understand the resource’s dependencies and lifecycle before applying the change.
Feature Flags and Progressive Delivery
Feature flags become particularly useful when combined with progressive delivery.
A team can deploy a new version, enable the feature for internal users, expand access gradually, and monitor service health throughout the process. If the new functionality causes problems, the team can disable the flag while investigating.
A typical workflow looks like this:
- Deploy the application with the new feature disabled.
- Enable the feature for internal users or a limited audience.
- Monitor errors, latency, resource consumption, and user outcomes.
- Increase exposure when the results meet the release criteria.
- Disable the feature if problems occur.
- Remove the temporary flag and obsolete code after the rollout is complete.
Feature flags do not replace observability, automated testing, deployment controls, or rollback mechanisms. They complement those practices by giving teams another way to control application behavior during a release.
Managing Feature-Flag Technical Debt
Every feature flag introduces another possible application state. As the number of flags increases, the number of combinations that may need testing can grow significantly.
Temporary flags should have an owner, a documented purpose, and a condition for removal. Once a feature is fully released and the old implementation is no longer needed, its temporary flag should usually be removed along with the obsolete code.
Long-lived operational flags may remain useful, but they need clear ownership, documented defaults, and monitoring.
Teams should also consider failure behavior. What happens if the flag-management service becomes unavailable? Should the application use its last known configuration, disable the feature, or continue using a safe default? The answer depends on the feature’s purpose and operational risk.
For critical operations, the default behavior should be chosen deliberately rather than left to an accidental configuration state.
Conclusion
Feature flags give application teams finer control over feature availability and release timing. Helm and Kubernetes can deliver flag configuration, while Terraform can use similar conditional logic to manage optional infrastructure resources.
Understanding the differences between these mechanisms helps platform engineers design safer deployment workflows and clearer operational boundaries.
A feature flag is one mechanism for controlling change. Progressive delivery combines such mechanisms with deployment strategies, traffic management, monitoring, and rollback to make that change safer.
Back to Certified Cloud Native Platform Engineering Associate Preparation