Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
567 changes: 567 additions & 0 deletions FEATURE_FLAGS_EXAMPLES.md

Large diffs are not rendered by default.

376 changes: 376 additions & 0 deletions FEATURE_FLAGS_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,376 @@
# Feature Flag System

A comprehensive feature flag system for gradual rollouts, A/B testing, and emergency feature toggles with user segmentation and targeting.

## Features

- βœ… **Feature Flag Evaluation Engine** - Sophisticated evaluation with caching
- βœ… **User Segmentation** - Target users by role, attributes, custom fields
- βœ… **Percentage Rollouts** - Gradual feature rollouts with consistent hashing
- βœ… **A/B Testing** - Multiple variant support with exposure control
- βœ… **Real-time Updates** - Redis-based flag updates across all instances
- βœ… **Environment-specific Flags** - Different configs for dev, staging, production
- βœ… **Flag Analytics** - Track evaluations, variants, and user exposure
- βœ… **Emergency Kill Switches** - Instantly disable features across all instances
- βœ… **Whitelist/Blacklist** - Override evaluation for specific users
- βœ… **Frontend SDK** - React hooks and components for easy integration

## Architecture

### Backend (NestJS)

```
app/backend/src/feature-flags/
β”œβ”€β”€ entities/
β”‚ β”œβ”€β”€ feature-flag.entity.ts # Main flag entity
β”‚ └── flag-evaluation.entity.ts # Evaluation tracking
β”œβ”€β”€ services/
β”‚ β”œβ”€β”€ flag-evaluation.service.ts # Core evaluation logic
β”‚ └── flag-cache.service.ts # Redis caching
β”œβ”€β”€ dto/
β”‚ └── create-feature-flag.dto.ts # DTOs for API
β”œβ”€β”€ decorators/
β”‚ └── feature-flag.decorator.ts # Route protection decorator
β”œβ”€β”€ guards/
β”‚ └── feature-flag.guard.ts # Guard for protected routes
β”œβ”€β”€ feature-flags.controller.ts # REST API endpoints
β”œβ”€β”€ feature-flags.service.ts # Main service
└── feature-flags.module.ts # Module configuration
```

### Frontend (Next.js/React)

```
app/frontend/lib/feature-flags/
β”œβ”€β”€ client.ts # API client
β”œβ”€β”€ hooks.tsx # React hooks
β”œβ”€β”€ components.tsx # React components
β”œβ”€β”€ types.ts # TypeScript types
└── index.ts # Public exports
```

## Quick Start

### Backend Setup

The feature flags module is already integrated into `app.module.ts`. No additional setup required.

### Frontend Setup

Wrap your app with the `FeatureFlagProvider`:

```tsx
import { FeatureFlagProvider } from '@/lib/feature-flags';

export default function App({ children }) {
return (
<FeatureFlagProvider
apiUrl="/api/feature-flags"
userId={currentUser?.id}
context={{ role: currentUser?.role }}
enablePolling={true}
pollingInterval={30000}
>
{children}
</FeatureFlagProvider>
);
}
```

## Usage Examples

### 1. Creating a Feature Flag

```typescript
POST /feature-flags
{
"key": "new_dashboard",
"name": "New Dashboard UI",
"description": "Redesigned dashboard with improved UX",
"type": "boolean",
"environment": "production",
"defaultValue": false,
"rolloutConfig": {
"percentage": 10
}
}
```

### 2. User Segmentation

```typescript
POST /feature-flags
{
"key": "premium_features",
"name": "Premium Features",
"type": "boolean",
"defaultValue": false,
"targetingRules": [
{
"name": "Premium Users",
"segments": [
[
{ "field": "role", "operator": "equals", "value": "premium" }
]
],
"value": true
},
{
"name": "Beta Testers",
"segments": [
[
{ "field": "email", "operator": "contains", "value": "@beta.com" }
]
],
"value": true
}
]
}
```

### 3. A/B Testing

```typescript
POST /feature-flags
{
"key": "checkout_flow",
"name": "Checkout Flow Test",
"type": "ab_test",
"defaultValue": "control",
"abTestConfig": {
"exposurePercentage": 50,
"variants": [
{ "name": "control", "weight": 50, "value": "original" },
{ "name": "variant_a", "weight": 25, "value": "simplified" },
{ "name": "variant_b", "weight": 25, "value": "detailed" }
]
}
}
```

### 4. Percentage Rollout

```typescript
POST /feature-flags
{
"key": "new_search",
"name": "New Search Algorithm",
"type": "rollout",
"defaultValue": false,
"rolloutConfig": {
"percentage": 25,
"seed": "search_v2"
}
}
```

### 5. Frontend - Using Hooks

```tsx
import { useFeatureFlag, useFeatureFlagValue, useABTestVariant } from '@/lib/feature-flags';

function MyComponent() {
// Simple boolean flag
const { isEnabled, isLoading } = useFeatureFlag('new_dashboard', false);

// Get typed value
const { value: maxItems } = useFeatureFlagValue<number>('max_items', 10);

// A/B test variant
const { variant } = useABTestVariant('checkout_flow');

if (isLoading) return <div>Loading...</div>;

return (
<div>
{isEnabled && <NewDashboard />}
{variant === 'variant_a' && <SimplifiedCheckout />}
{variant === 'variant_b' && <DetailedCheckout />}
<ItemList maxItems={maxItems} />
</div>
);
}
```

### 6. Frontend - Using Components

```tsx
import { FeatureGate, ABTest } from '@/lib/feature-flags';

function App() {
return (
<div>
<FeatureGate
flagKey="new_dashboard"
fallback={<OldDashboard />}
>
<NewDashboard />
</FeatureGate>

<ABTest
flagKey="checkout_flow"
variants={{
control: <OriginalCheckout />,
variant_a: <SimplifiedCheckout />,
variant_b: <DetailedCheckout />,
}}
/>
</div>
);
}
```

### 7. Backend - Protecting Routes

```typescript
import { FeatureFlag } from './feature-flags/decorators/feature-flag.decorator';
import { FeatureFlagGuard } from './feature-flags/guards/feature-flag.guard';

@Controller('advanced')
@UseGuards(FeatureFlagGuard)
export class AdvancedController {
@Get()
@FeatureFlag('advanced_analytics')
getAdvancedAnalytics() {
// Only accessible if feature flag is enabled for user
return { data: 'advanced analytics' };
}
}
```

### 8. Emergency Kill Switch

```typescript
POST /feature-flags/problematic_feature/kill-switch
{
"reason": "Critical bug in production - causing checkout failures"
}
```

This immediately:
- Sets flag status to `inactive`
- Sets default value to `false`
- Clears cache across all instances
- Publishes update to all connected clients

### 9. Whitelist/Blacklist Management

```typescript
// Add user to whitelist (always gets feature)
POST /feature-flags/new_feature/whitelist/user-123

// Remove from whitelist
DELETE /feature-flags/new_feature/whitelist/user-123
```

### 10. Analytics

```typescript
GET /feature-flags/new_dashboard/analytics?startDate=2026-01-01&endDate=2026-02-01

Response:
{
"flagKey": "new_dashboard",
"totalEvaluations": 15230,
"uniqueUsers": 8945,
"valueDistribution": {
"true": 1523,
"false": 13707
},
"variantDistribution": {},
"reasonDistribution": {
"rollout": 1523,
"default": 13707
}
}
```

## API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/feature-flags` | Create new flag |
| GET | `/feature-flags` | List all flags |
| GET | `/feature-flags/:key` | Get flag by key |
| PUT | `/feature-flags/:key` | Update flag |
| DELETE | `/feature-flags/:key` | Archive flag |
| POST | `/feature-flags/evaluate` | Evaluate single flag |
| POST | `/feature-flags/bulk-evaluate` | Evaluate multiple flags |
| POST | `/feature-flags/:key/toggle` | Toggle flag status |
| POST | `/feature-flags/:key/kill-switch` | Emergency disable |
| GET | `/feature-flags/:key/analytics` | Get analytics |
| POST | `/feature-flags/:key/whitelist/:userId` | Add to whitelist |
| DELETE | `/feature-flags/:key/whitelist/:userId` | Remove from whitelist |
| GET | `/feature-flags/cache/stats` | Cache statistics |

## Flag Evaluation Order

1. **Inactive Check** - Return default if flag is inactive
2. **Blacklist** - Return false if user is blacklisted
3. **Whitelist** - Return true if user is whitelisted
4. **Targeting Rules** - Evaluate segment conditions
5. **A/B Test** - Assign variant based on consistent hashing
6. **Rollout** - Check percentage rollout
7. **Default Value** - Return default value

## Segmentation Operators

- `equals` - Exact match
- `notEquals` - Not equal
- `in` - Value in array
- `notIn` - Value not in array
- `contains` - String/array contains
- `greaterThan` - Numeric comparison
- `lessThan` - Numeric comparison

## Best Practices

1. **Use Meaningful Keys** - `new_dashboard` not `flag_123`
2. **Add Descriptions** - Document what the flag controls
3. **Set Environments** - Use proper environment flags
4. **Monitor Analytics** - Track flag usage and impact
5. **Clean Up** - Archive unused flags
6. **Test Gradually** - Start with small rollout percentages
7. **Use Kill Switches Wisely** - Document the reason
8. **Cache Appropriately** - Enable polling for real-time updates

## Environment Variables

```env
REDIS_URL=redis://localhost:6379
DATABASE_PATH=./database.sqlite
```

## Testing

The system includes comprehensive evaluation logic with consistent hashing for deterministic rollouts and variant assignment.

## Performance

- **Redis Caching** - Sub-millisecond flag lookups
- **Bulk Evaluation** - Evaluate multiple flags in single request
- **Real-time Updates** - Instant propagation via Redis pub/sub
- **Analytics** - Indexed queries for fast analytics

## Security

- Feature flags can be protected with guards
- User context validated before evaluation
- Analytics track all evaluations for audit

## Acceptance Criteria Status

βœ… **Flag evaluation working** - Comprehensive evaluation engine with caching
βœ… **Segmentation correct** - Multi-field segments with various operators
βœ… **Rollouts gradual** - Percentage-based with consistent hashing
βœ… **A/B tests functional** - Multi-variant support with exposure control
βœ… **Kill switches responsive** - Instant disable via Redis pub/sub

## Future Enhancements

- [ ] Scheduled flag changes
- [ ] Flag dependencies
- [ ] Advanced analytics dashboard
- [ ] Audit log/history
- [ ] Import/export configurations
- [ ] Webhooks for flag changes
Loading