Feature Toggle Types
Types of Feature Flags
Release Toggles
// Control feature visibility during rollout
public function isNewCheckoutEnabled(): bool
{
return $this->featureFlagManager->isEnabled('new_checkout');
}
// Usage in code
public function getCheckoutAction()
{
if ($this->isNewCheckoutEnabled()) {
return $this->actionFactory->create(
\Vendor\Checkout\Controller\Index\NewIndex::class
);
}
return $this->actionFactory->create(
\Magento\Checkout\Controller\Index\Index::class
);
}
Experiment Toggles
// A/B testing configuration
public function getHomepageVersion(): string
{
$userId = $this->customerSession->getCustomerId();
// Deterministic assignment based on user ID
$hash = crc32((string)$userId);
$percentage = $hash % 100;
if ($percentage < 50) {
return 'control';
}
return 'variant_a';
}
Ops Toggles
// Emergency kill switches
public function isPaymentGatewayEnabled(): bool
{
return $this->featureFlagManager->isEnabled('payment_gateway');
}
// Disable broken payment gateway immediately
if ($this->hasPaymentErrors()) {
$this->configWriter->save('feature_flags/payment_gateway', false);
}
Permission Toggles
// Admin-only features
public function isAdvancedReportingEnabled(): bool
{
if (!$this->authorization->isAllowed('Vendor_AdvancedReporting::view')) {
return false;
}
return $this->featureFlagManager->isEnabled('advanced_reporting');
}
Migration Toggles
// Control migration traffic
public function useNewOrderService(): bool
{
$rolloutPercentage = (int)$this->config->get('migration/order_rollout');
return rand(1, 100) <= $rolloutPercentage;
}
Flag Implementation
Feature Flag System
Database Storage
CREATE TABLE feature_flags (
id INT AUTO_INCREMENT PRIMARY KEY,
flag_key VARCHAR(50) UNIQUE NOT NULL,
is_enabled BOOLEAN DEFAULT FALSE,
description TEXT,
rollout_percentage INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- Sample flags
INSERT INTO feature_flags (flag_key, is_enabled, description, rollout_percentage) VALUES
('new_checkout', FALSE, 'New checkout flow', 0),
('product_recommendations', TRUE, 'AI product recommendations', 100),
('migration_orders', FALSE, 'New order service migration', 25);
Service Implementation
namespace Vendor\FeatureFlag\Service;
class FeatureFlagService implements FeatureFlagInterface
{
public function __construct(
private ResourceConnection $resource,
private CacheInterface $cache,
private ConfigInterface $config
) {}
public function isEnabled(string $flagKey): bool
{
$cacheKey = "feature_flag_{$flagKey}";
$cached = $this->cache->load($cacheKey);
if ($cached !== false) {
return (bool)$cached;
}
$connection = $this->resource->getConnection();
$select = $connection->select()
->from($this->resource->getTableName('feature_flags'))
->where('flag_key = ?', $flagKey);
$result = $connection->fetchRow($select);
if (!$result) {
return false; // Default to disabled
}
$isEnabled = (bool)$result['is_enabled'];
$this->cache->save($isEnabled ? '1' : '0', $cacheKey, [], 60);
return $isEnabled;
}
public function getRolloutPercentage(string $flagKey): int
{
$connection = $this->resource->getConnection();
$select = $connection->select()
->from($this->resource->getTableName('feature_flags'))
->where('flag_key = ?', $flagKey);
$result = $connection->fetchRow($select);
return (int)($result['rollout_percentage'] ?? 0);
}
}
Configuration File
// app/config/feature-flags.json
{
"flags": {
"new_checkout": {
"enabled": false,
"description": "New checkout flow",
"rollout_percentage": 0
},
"product_recommendations": {
"enabled": true,
"description": "AI product recommendations",
"rollout_percentage": 100
}
}
}
CLI Management
# Enable a flag
php bin/magento feature-flag:enable new_checkout
# Disable a flag
php bin/magento feature-flag:disable new_checkout
# Set rollout percentage
php bin/magento feature-flag:rollout new_checkout 25
# List all flags
php bin/magento feature-flag:list
# Show flag status
php bin/magento feature-flag:status new_checkout
Gradual Rollout
Rollout Strategies
Percentage-Based Rollout
public function shouldUseNewFeature(string $featureKey, int $userId): bool
{
$rolloutPercentage = $this->flagService->getRolloutPercentage($featureKey);
if ($rolloutPercentage === 0) {
return false;
}
if ($rolloutPercentage === 100) {
return true;
}
// Deterministic hash-based assignment
$hash = crc32($featureKey . $userId);
return ($hash % 100) < $rolloutPercentage;
}
User Segment Rollout
public function isFeatureEnabledForUser(string $featureKey, int $customerId): bool
{
$customer = $this->customerRepository->getById($customerId);
// Rollout to specific groups
$groups = $this->flagService->getTargetGroups($featureKey);
if (!empty($groups) && !in_array($customer->getGroupId(), $groups)) {
return false;
}
// Rollout to specific websites
$websites = $this->flagService->getTargetWebsites($featureKey);
if (!empty($websites) && !in_array($customer->getWebsiteId(), $websites)) {
return false;
}
return $this->shouldUseNewFeature($featureKey, $customerId);
}
Rollout Stages
Stage 1: Internal (0-5%)
- Team members only
- Verify basic functionality
- Monitor for critical errors
Stage 2: Beta (5-25%)
- Selected customers
- Gather feedback
- Performance validation
Stage 3: Gradual (25-75%)
- Increase percentage weekly
- Monitor metrics
- Adjust based on feedback
Stage 4: Full (75-100%)
- Complete rollout
- Remove flag
- Clean up code
Rollback Automation
// Auto-rollback on error threshold
public function monitorAndRollback(string $featureKey): void
{
$errorRate = $this->monitoring->getErrorRate($featureKey);
$threshold = $this->flagService->getRollbackThreshold($featureKey);
if ($errorRate > $threshold) {
$this->flagService->disable($featureKey);
$this->alertService->send('Feature flag auto-rolled back', [
'flag' => $featureKey,
'error_rate' => $errorRate,
'threshold' => $threshold
]);
}
}
Flag Lifecycle Management
Flag Lifecycle
Creation
// Create new flag
$this->flagService->create([
'flag_key' => 'new_search_algorithm',
'is_enabled' => false,
'description' => 'Elasticsearch 8.x search algorithm',
'rollout_percentage' => 0,
'owner' => 'search-team',
'created_by' => $this->adminSession->getUser()->getId()
]);
Monitoring
// Track flag usage and metrics
public function trackFlagUsage(string $flagKey, string $action): void
{
$this->statsd->increment("feature_flags.{$flagKey}.{$action}");
$this->logger->info('Feature flag used', [
'flag' => $flagKey,
'action' => $action,
'user_id' => $this->adminSession->getUser()->getId()
]);
}
Cleanup
// Remove flag after full rollout
public function removeFlag(string $flagKey): void
{
// 1. Verify 100% rollout for 2+ weeks
$rolloutHistory = $this->flagService->getRolloutHistory($flagKey);
if (!$this->isFullyRolledOut($rolloutHistory)) {
throw new \Exception('Cannot remove flag not fully rolled out');
}
// 2. Remove flag references from code
$this->codeCleanupService->removeFlagReferences($flagKey);
// 3. Remove flag from database
$this->flagService->delete($flagKey);
// 4. Update documentation
$this->documentationService->removeFlag($flagKey);
}
Documentation Template
## Feature Flag: new_checkout
**Owner:** Checkout Team
**Created:** 2024-01-15
**Status:** In Progress (75% rollout)
**Target Completion:** 2024-03-01
### Description
New checkout flow with one-page checkout and address validation.
### Rollout Plan
- [x] Internal testing (0-5%)
- [x] Beta customers (5-25%)
- [x] Partial rollout (25-75%)
- [ ] Full rollout (75-100%)
- [ ] Flag removal
### Metrics
- Conversion rate: +2.3%
- Error rate: 0.02%
- Performance: 150ms avg
### Rollback Trigger
Error rate > 1% or conversion drop > 5%
Flag Audit
# Find unused flags
rg 'isEnabled.*old_feature' app/code/ --include='*.php'
# Find flags with low usage
mysql -u root -p magento -e "
SELECT flag_key, last_used_at
FROM feature_flags
WHERE last_used_at < DATE_SUB(NOW(), INTERVAL 30 DAY)
"
# Generate flag report
php bin/magento flag:report
Practice Problems
Implement a complete feature flag system for gradual checkout rollout with percentage-based control.
Manage the lifecycle of a feature flag from creation to removal after successful rollout.
Quiz
1. What is a release toggle?
2. What is the recommended rollout order?
3. When should a feature flag be removed?
4. What triggers automatic rollback?
Flashcards
Question
What are the 4 types of feature flags?
Click to reveal answer
Answer
Release toggles, experiment toggles, ops toggles, permission toggles
Question
How does percentage-based rollout work?
Click to reveal answer
Answer
Hash-based assignment ensures consistent user experience within same percentage
Question
When to remove a flag?
Click to reveal answer
Answer
After 2+ weeks at 100% rollout with stable metrics
Question
What is auto-rollback?
Click to reveal answer
Answer
Automatic flag disable when error rate exceeds threshold
Question
What tracks flag usage?
Click to reveal answer
Answer
StatsD metrics and application logging
Revision Notes
Key Takeaways
- 1. 4 flag types: release, experiment, ops, permission toggles
- 2. Use hash-based assignment for consistent percentage rollout
- 3. Rollout stages: Internal (0-5%) → Beta (5-25%) → Gradual (25-75%) → Full (75-100%)
- 4. Auto-rollback on error rate threshold prevents user impact
- 5. Remove flags after 2+ weeks stable at 100% to avoid code debt
- 6. Document flags with owner, rollout plan, and metrics
Interview Tips
- • Explain the different types of feature flags
- • How do you implement percentage-based rollout?
- • What is the lifecycle of a feature flag?
- • How do you prevent feature flag debt?
- • Describe automatic rollback implementation
Cheat Sheet
Feature Flags Cheat Sheet
Types:
- Release: visibility during rollout
- Experiment: A/B testing
- Ops: emergency kill switches
- Permission: admin-only access
Rollout Stages:
- Internal: 0-5%
- Beta: 5-25%
- Gradual: 25-75%
- Full: 75-100%
Lifecycle:
- Create (disabled)
- Enable (gradual %)
- Monitor metrics
- Full rollout (100%)
- Remove (2+ weeks stable)
Auto-Rollback:
Trigger: error rate > threshold
Action: disable flag immediately