Skip to content
intermediatePhase 48 · Distributed Systems

Graceful Degradation

Reduce functionality gracefully when components fail.

30m
0 problems
Topic Progress0%

What is Graceful Degradation

What is Graceful Degradation

Graceful degradation maintains core functionality while disabling non-essential features during failures.

The Concept

Full Functionality:
[Core] + [Feature A] + [Feature B] + [Feature C]

Degraded Mode:
[Core] + [Feature A] + [ ] + [ ]

Minimal Mode:
[Core] + [ ] + [ ] + [ ]

Why Degrade Gracefully?

Without degradation:
Dependency fails → Entire system fails → Users see error page

With degradation:
Dependency fails → Feature disabled → Users still use core

Degradation Levels

Level Status User Experience
L0 All systems up Full functionality
L1 Minor degradation Some features unavailable
L2 Moderate degradation Major features unavailable
L3 Severe degradation Only core features
L4 Critical failure Error page or maintenance

Examples

E-commerce:
- L0: Full site
- L1: Recommendations down, rest works
- L2: Reviews + recommendations down
- L3: Only browse + buy
- L4: Error page

Social Media:
- L0: Full experience
- L1: Analytics down
- L2: Feed + analytics down
- L3: Post + read only
- L4: Error page

Fallback Strategies

Fallback Strategies

Strategy Types

1. Cached Fallback:
   Return cached data when live fails

2. Default Fallback:
   Return default/empty response

3. Partial Fallback:
   Return partial results

4. Alternative Source:
   Use backup data source

Implementation

class FallbackManager:
    def __init__(self, cache, primary_source, fallback_source):
        self.cache = cache
        self.primary = primary_source
        self.fallback = fallback_source
    
    def get_data(self, key):
        # Try primary
        try:
            data = self.primary.get(key)
            self.cache.set(key, data, ttl=300)
            return data
        except Exception:
            pass
        
        # Try cache
        cached = self.cache.get(key)
        if cached:
            return cached
        
        # Try fallback
        try:
            return self.fallback.get(key)
        except Exception:
            return self.get_default(key)
    
    def get_default(self, key):
        return {
            'status': 'unavailable',
            'message': 'Service temporarily unavailable'
        }

Fallback Patterns

Pattern Description Latency
Cached Return cached data Low
Default Return default value Very Low
Partial Return partial results Medium
Alternative Use backup source Higher

Best Practices

  1. Always have a fallback
  2. Cache successful responses
  3. Set appropriate TTLs
  4. Inform users of degraded mode
  5. Monitor fallback usage

Circuit Breakers

Circuit Breakers in Degradation

Integration

Normal: Full functionality
          ↓
Circuit opens: Feature disabled
          ↓
Circuit closed: Feature restored

Implementation

class FeatureToggles:
    def __init__(self):
        self.features = {}
    
    def register(self, feature_name, circuit_breaker):
        self.features[feature_name] = {
            'circuit': circuit_breaker,
            'enabled': True
        }
    
    def is_enabled(self, feature_name):
        if feature_name not in self.features:
            return False
        
        feature = self.features[feature_name]
        
        # Check if manually disabled
        if not feature['enabled']:
            return False
        
        # Check circuit breaker
        return not feature['circuit'].is_open
    
    def disable(self, feature_name):
        self.features[feature_name]['enabled'] = False
    
    def enable(self, feature_name):
        self.features[feature_name]['enabled'] = True

# Usage
features = FeatureToggles()
features.register('recommendations', CircuitBreaker())
features.register('reviews', CircuitBreaker())

def get_product(product_id):
    product = db.get_product(product_id)
    
    if features.is_enabled('recommendations'):
        product['recommendations'] = get_recommendations(product_id)
    else:
        product['recommendations'] = []
    
    return product

Degradation Monitoring

def monitor_degradation():
    for feature_name, feature in features.features.items():
        state = feature['circuit'].state
        metrics.gauge(f'feature.{feature_name}.state',
                     ['closed', 'open', 'half-open'].index(state))
        
        if state == 'open':
            alert(f'Feature {feature_name} is degraded')

Best Practices

  1. Use circuit breakers for each dependency
  2. Register feature toggles for all external calls
  3. Monitor degradation levels
  4. Alert on feature degradation
  5. Test degradation scenarios

Practice Problems

0/3solved
Design Graceful Degradation System

Design a scalable Graceful Degradation system. Cover high-level architecture, data model, and API design.

Solution
// Complete system design:
// - Functional + Non-functional requirements
// - Capacity estimation
// - Data model (SQL/NoSQL choice)
// - API endpoints
// - Component architecture
// - Scaling strategy
// - Monitoring & reliability
Graceful Degradation Scaling

How would you scale Graceful Degradation to handle 10x the current load? Identify bottlenecks and solutions.

Solution
// Scaling approach:
// 1. Load balancing
// 2. Database sharding/replication
// 3. Cache layer (Redis)
// 4. CDN for static assets
// 5. Async processing (queues)
// 6. Microservices decomposition
Graceful Degradation Failure Modes

Analyze potential failure modes for Graceful Degradation and design mitigation strategies.

Solution
// Failure mitigation:
// 1. Redundancy (multi-AZ)
// 2. Circuit breakers
// 3. Retry with backoff
// 4. Dead letter queues
// 5. Health checks
// 6. Graceful degradation

Quiz

1. What is graceful degradation?

Question 1 options

2. What is a fallback strategy?

Question 2 options

3. How do circuit breakers help degradation?

Question 3 options

4. What is L2 degradation?

Question 4 options

5. Why cache successful responses for fallback?

Question 5 options

Flashcards

Question

What is graceful degradation?

Answer

Maintaining core functionality while disabling non-essential features during failures

Question

Fallback strategies?

Answer

1) Cached fallback, 2) Default fallback, 3) Partial fallback, 4) Alternative source

Question

How circuit breakers enable degradation?

Answer

Automatically disable features when dependencies fail, allowing core to continue functioning

Question

Degradation levels?

Answer

L0 (full) → L1 (minor) → L2 (major) → L3 (core only) → L4 (error page)

Question

Why cache for fallback?

Answer

Cached responses provide fallback data when primary source is unavailable

Revision Notes

Key Takeaways

  • 1.Graceful degradation maintains core while disabling features
  • 2.Always have fallback strategies (cached, default, alternative)
  • 3.Circuit breakers enable automatic degradation
  • 4.Monitor degradation levels and alert on issues
  • 5.Test degradation scenarios regularly

Interview Tips

  • Explain degradation levels and examples
  • Discuss fallback strategy selection
  • Mention circuit breaker integration
  • Give real-world degradation examples

Cheat Sheet

Cheat Sheet: Graceful Degradation

Concept

Core functionality continues while features disabled

Levels

L0: Full
L1: Minor disabled
L2: Major disabled
L3: Core only
L4: Error page

Fallback Strategies

  1. Cached: Return cached data
  2. Default: Return default value
  3. Partial: Return partial results
  4. Alternative: Use backup source

Circuit Breakers

  • Auto-disable features
  • Monitor degradation
  • Alert on open circuits