PERFORMANCE LOOP FIX
Comprehensive guidelines for AI-assisted development within the Editor platform
๐จ CRITICAL FIX: Infinite Performance Metrics Loop
Emergency fix for recursive database operations that killed the app
๐ฅ Critical Issue Report
Severity: ๐จ CRITICAL - App becomes completely unusable
Impact: Infinite loop causing browser crash and complete application failure
User Report: "I got an infinite amount (loop) of messages that killed our app"
Error Pattern
โ
Upserted record in performance-metrics: metric_1753724371256_aeq604dki
โ
Upserted record in performance-metrics: metric_1753724371256_5b5cvknb8
โ
Upserted record in performance-metrics: metric_1753724371257_6qnfjflf6
โ
Upserted record in performance-metrics: metric_1753724371257_e9j9xpign
[INFINITE LOOP CONTINUES...]
๐ Root Cause Analysis
The Infinite Recursion Chain
The issue was caused by recursive performance tracking in the LocalDatabaseService:
graph TB
A[User creates block] --> B[upsert called]
B --> C[recordPerformanceMetric triggered]
C --> D[upsert 'performance-metrics']
D --> E[recordPerformanceMetric triggered again]
E --> D
style A fill:#e1f5fe
style D fill:#ffebee
style E fill:#ffebee
Technical Breakdown
- Initial Trigger: User creates a block
- Database Operation:
upsert()method called to save block - Performance Tracking:
recordPerformanceMetric()automatically triggered - Metrics Storage: Performance metric stored via
upsert('performance-metrics', ...) - Recursion: That
upserttriggersrecordPerformanceMetric()again - Infinite Loop: Steps 4-5 repeat infinitely until browser crashes
Code Location
File: apps/singularity/src/app/core/services/local-database.service.ts
Before (Problematic Code):
// Line 370: Every upsert triggers performance recording
tap(() => this.recordPerformanceMetric('upsert', startTime, true, { storeName, id: data.id })),
// Line 649: Performance recording stores in database (causing recursion)
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
// ... create metric object
// ๐จ PROBLEM: This triggers another upsert, causing infinite recursion
this.upsert('performance-metrics', { ...metric, id: `...` })
.subscribe({
error: (error) => console.warn('Failed to record performance metric:', error)
});
}
โ Fix Applied
Recursion Prevention Guard
Added a recursion guard to prevent performance metrics from tracking themselves:
/**
* Record performance metrics (with recursion prevention)
*/
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
// ๐ก๏ธ CRITICAL: Prevent infinite recursion - don't record metrics for performance-metrics operations
if (details?.storeName === 'performance-metrics') {
return; // Exit early, don't track metrics for metrics operations
}
const metric: PerformanceMetric = {
operation,
timestamp: new Date(),
duration: performance.now() - startTime,
success,
details
};
// Store in performance metrics (async, don't block, with recursion protection)
this.upsert('performance-metrics', { ...metric, id: `metric_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` })
.subscribe({
error: (error) => console.warn('Failed to record performance metric:', error)
});
}
Fix Logic
- Guard Check: Before recording metrics, check if the operation is on 'performance-metrics' store
- Early Return: If yes, return immediately without recording (prevents recursion)
- Normal Flow: For all other operations, record metrics as usual
๐งช Testing Strategy
Immediate Verification
- Clear Browser Storage: DevTools โ Application โ Storage โ Clear storage
- Navigate to Logic Builder: Go to
/logic-builder - Create Test Block: Click "Create Test Block"
- Monitor Console: Should see NO infinite performance metric messages
Expected Behavior
โ Success Indicators:
- Block created successfully
- Single performance metric recorded (not infinite)
- UI remains responsive
- No browser crashes
โ Failure Indicators:
- Infinite console spam
- Browser becoming unresponsive
- App crashes
๐ Performance Impact Analysis
Before Fix (Broken)
- Performance: โ App crashes within seconds
- Resource Usage: โ Infinite memory consumption
- User Experience: โ Completely unusable
After Fix (Working)
- Performance: โ Normal operation restored
- Resource Usage: โ Controlled memory usage
- User Experience: โ Smooth, responsive interface
๐ก๏ธ Prevention Strategies
Code Review Guidelines
- Recursive Operation Awareness: Always check if operations can trigger themselves
- Performance Tracking: Be cautious when tracking operations that store data
- Guard Clauses: Implement recursion prevention for performance monitoring
- Testing: Test performance features under real usage scenarios
NGXS Best Practices
Based on NGXS vs NgRx comparison, NGXS provides more opinionated state management which helps prevent such issues through structured approaches to side effects and state updates.
Key Principles:
- Structured State Management: Use proper action/state patterns
- Side Effect Isolation: Keep performance tracking separate from core operations
- Immutable Updates: Prevent accidental state mutations that could trigger loops
Database Operation Patterns
// โ
GOOD: Conditional performance tracking
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
// Prevent recursion for self-referential operations
if (details?.storeName === 'performance-metrics') {
return;
}
// ... rest of implementation
}
// โ BAD: Unconditional tracking that can cause recursion
private recordPerformanceMetric(operation: string, startTime: number, success: boolean, details?: any): void {
// No guard - can cause infinite recursion
this.upsert('performance-metrics', metric);
}
๐ฏ Lessons Learned
Critical Insights
- Performance Monitoring Can Be Dangerous: Monitoring systems can become the bottleneck
- Recursion Prevention is Mandatory: Always guard against self-referential operations
- Early Detection is Key: Performance issues should be caught in development
- User Feedback is Invaluable: The user caught this critical issue immediately
Development Practices
- Test Edge Cases: Always test performance features under load
- Monitor Resource Usage: Watch for unusual memory/CPU patterns
- Implement Safeguards: Add circuit breakers for recursive operations
- Document Side Effects: Clearly document operations that can trigger other operations
๐ Resolution Status
โ
FIXED - Infinite loop eliminated with recursion prevention guard
โ
TESTED - Performance metrics work correctly without recursion
โ
DOCUMENTED - Full analysis and prevention strategies documented
โ
STABLE - App performance restored to normal operation
The application is now safe from recursive performance tracking loops! ๐
๐ฎ Future Enhancements
Monitoring Improvements
- Implement rate limiting for performance metrics
- Add circuit breaker pattern for database operations
- Create performance budget alerts to catch issues early
- Add operation depth tracking to detect deep recursion
Error Resilience
- Implement graceful degradation when metrics fail
- Add emergency stop mechanisms for runaway operations
- Create health checks for database service integrity