Feature Flags in Microservices
IntermediateFeature flags decouple deployment from release; toggle features per environment or user segment without redeploying, enabling dark launches and A/B tests.
Overview
Feature flags (also called feature toggles or feature switches) decouple code deployment from feature release. You deploy code with a new feature wrapped in a flag check — the feature is off by default. Operations or product teams enable it for specific environments, user segments, or percentages of traffic without redeploying. This enables: dark launches (deploy to production, enable for 1% of users to test at scale), A/B testing (compare two implementations in production), kill switches (instantly disable a problematic feature without rollback), and gradual rollouts (canary via traffic percentage). Popular platforms: LaunchDarkly, Unleash, Flagsmith, OpenFeature (vendor-neutral SDK standard).
Simple feature flag with Spring Boot and properties
The simplest approach uses configuration properties — a boolean that can be changed via environment variable, Kubernetes ConfigMap reload, or Spring Cloud Config. This works well for on/off flags that change infrequently. For user-segment or percentage-based flags, use a dedicated feature flag platform.
// application.yml — feature flags as properties
features:
new-checkout-flow: true
experimental-pricing: false
max-order-size-check: true
// Configuration properties class
@ConfigurationProperties(prefix = "features")
@Component
public class FeatureFlags {
private boolean newCheckoutFlow;
private boolean experimentalPricing;
private boolean maxOrderSizeCheck;
// getters/setters or use @ConstructorBinding record
}
// Usage in service
@Service
public class CheckoutService {
private final FeatureFlags flags;
public CheckoutResult checkout(Cart cart, User user) {
if (flags.isNewCheckoutFlow()) {
return newCheckoutFlowService.process(cart, user);
}
return legacyCheckoutService.process(cart, user);
}
}
// Toggle without redeployment via K8s ConfigMap reload
# kubectl patch configmap app-config
# --patch '{"data":{"features.new-checkout-flow":"true"}}'
# (requires spring.config.import=kubernetes: + @RefreshScope or restart)OpenFeature SDK — vendor-neutral feature flags
OpenFeature is a CNCF standard SDK that provides a vendor-neutral API for feature flag evaluation. You write code against the OpenFeature API; the provider (LaunchDarkly, Unleash, Flagsmith, or a custom in-process provider) handles flag storage and evaluation. This prevents vendor lock-in and allows switching providers without changing application code.
<!-- pom.xml -->
<dependency>
<groupId>dev.openfeature</groupId>
<artifactId>sdk</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>dev.openfeature.contrib.providers</groupId>
<artifactId>unleash</artifactId>
<version>0.0.4</version>
</dependency>
// Configure provider (Unleash example)
@Configuration
public class FeatureFlagConfig {
@Bean
public OpenFeatureAPI openFeatureAPI() {
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
UnleashProvider provider = new UnleashProvider(
UnleashConfig.newBuilder()
.appName("order-service")
.unleashAPI("http://unleash:4242/api")
.customHttpHeader("Authorization", "*:development.secret")
.build()
);
api.setProvider(provider);
return api;
}
}
// Usage — evaluated at runtime, context-aware
@Service
public class PricingService {
private final Client featureClient;
public BigDecimal calculatePrice(Order order, User user) {
EvaluationContext ctx = new MutableContext()
.add("userId", user.getId())
.add("country", user.getCountry())
.add("plan", user.getPlan());
boolean useNewPricing = featureClient.getBooleanValue(
"new-pricing-algorithm", false, ctx);
return useNewPricing
? newPricingEngine.calculate(order, user)
: legacyPricingEngine.calculate(order, user);
}
}Kill switches and gradual rollout strategies
Kill switches are flags designed for emergency shutdown of a feature that is causing incidents — they should be testable before needed, have clear ownership, and be executable by on-call engineers without code changes. Gradual rollout (percentage-based) enables canary testing at the application logic level, independent of infrastructure-level canary deployments.
// Kill switch pattern — operational readiness
@Component
public class PaymentGatewayKillSwitch {
private final Client featureClient;
private final MeterRegistry meterRegistry;
public void processPayment(PaymentRequest req) {
boolean gatewayEnabled = featureClient.getBooleanValue(
"payment-gateway-v2-enabled", true);
if (!gatewayEnabled) {
// Kill switch activated — fall back to v1
meterRegistry.counter("payment.kill_switch.activated").increment();
log.warn("Payment gateway v2 kill switch activated — using v1");
paymentGatewayV1.process(req);
return;
}
paymentGatewayV2.process(req);
}
}
// Percentage rollout (in Unleash / LaunchDarkly configuration)
// Flag: "new-order-summary"
// Strategy: gradualRollout
// percentage: 10% → enable for 10% of users
// stickiness: userId → same user always gets same variant
// Increment rollout without redeployment:
// Day 1: 1% → verify error rates, latency
// Day 2: 10% → monitor at scale
// Day 3: 50% → confirm acceptable metrics
// Day 4: 100% → full rollout
// Day 5: remove flag from code (don't leave dead flags)Key Points to Remember
- 1Feature flags decouple deployment (code merged and deployed) from release (feature visible to users)
- 2OpenFeature provides a vendor-neutral SDK — swap providers (LaunchDarkly, Unleash, Flagsmith) without code changes
- 3Evaluation context (userId, country, plan) enables targeting: specific user segments get different flag values
- 4Kill switches must be pre-tested and accessible to on-call engineers — not just developers — for true operational value
- 5Gradual rollout (1% → 10% → 50% → 100%) enables safe production validation before full release
- 6Remove flags from code after full rollout — dead flags become technical debt and confuse new developers
Interview Questions
Sign in to ask AriaWhat is the difference between a feature flag and a configuration property?
How do feature flags enable dark launches and why is this valuable?
What is OpenFeature and why would you use it over a vendor SDK directly?
What is a kill switch flag and how should it be designed for operational readiness?
How would you implement a gradual rollout of a new checkout flow to 5% of users in production?
Ask Aria about Feature Flags in Microservices
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.