Architecture Decision Record: Device Detection Strategy
Status: Accepted
Date: 2025-01-21
Author: Feature Flags Team
Context and Problem Statement
The feature flags plugin needs device detection capability for targeting rules (e.g., showing features only to mobile users, A/B testing by platform). The initial implementation used regex-heavy detection which raised performance concerns.
Should we use a full-featured library like ua-parser-js
or implement optimized built-in detection?
Decision Drivers
- Performance: Must work efficiently in serverless/edge environments
- Bundle Size: Critical for cold starts and deployment limits
- Accuracy: Should correctly identify common devices/browsers
- Maintenance: Minimize ongoing maintenance burden
- Flexibility: Support various deployment scenarios
Considered Options
Option 1: Always Use ua-parser-js
- ✅ 99%+ accuracy
- ✅ Regular updates
- ✅ Rich data (versions, models)
- ❌ 60KB bundle size
- ❌ Slower cold starts
- ❌ External dependency
Option 2: Built-in Detection Only
- ✅ 2KB bundle size
- ✅ Fast performance
- ✅ No dependencies
- ❌ 95% accuracy
- ❌ Manual maintenance
- ❌ Limited data
Option 3: Dual Approach (Selected)
- ✅ 2KB default size
- ✅ Optional enhanced mode
- ✅ User choice
- ✅ Best of both worlds
- ⚠️ More complex
- ⚠️ Two code paths
Decision Outcome
Chosen option: Option 3 - Dual Approach
Built-in optimized detection as default, with optional ua-parser-js
integration.
Implementation
typescript
// Default: Built-in detection (2KB)
const uaCache = new Map<string, UserAgentInfo>();
function parseUserAgent(userAgent: string): UserAgentInfo {
// Check cache
const cached = uaCache.get(userAgent);
if (cached) return cached;
// Optimized pattern matching
const info = {
device: detectDevice(ua),
browser: detectBrowser(ua),
os: detectOS(ua),
platform: detectPlatform(ua),
};
// LRU cache
uaCache.set(userAgent, info);
return info;
}
Positive Consequences
- Performance: 10x faster for cached requests
- Flexibility: Users choose accuracy vs performance
- Compatibility: Works in all environments
- Bundle: Minimal default impact
Negative Consequences
- Complexity: Two code paths to maintain
- Documentation: Must explain both options
- Testing: More test scenarios
Performance Metrics
Metric | Built-in | ua-parser-js |
---|---|---|
Bundle Size | +2KB | +60KB |
First Parse | 0.1ms | 2ms |
Cached Parse | 0.01ms | 0.01ms |
Accuracy | 95% | 99%+ |
Cold Start Impact | Negligible | +50-100ms |
Migration Path
- Default remains lightweight
- Users can opt-in to enhanced:bash
bun add ua-parser-js
- Configure plugin:typescript
featureFlags({ parsing: { useEnhancedUA: true }, });