Graceful Degradation and Fallbacks

Maintaining functionality during failures:

Graceful Degradation Strategies:

  • Feature degradation
  • Reduced functionality
  • Simplified processing
  • Cached responses
  • Static content
  • Default values
  • User communication

Example Graceful Degradation (JavaScript):

// JavaScript graceful degradation example
class ProductPage {
  constructor() {
    this.productId = this.getProductIdFromUrl();
    this.cacheKey = `product_${this.productId}`;
    this.cacheExpiry = 30 * 60 * 1000; // 30 minutes
  }
  
  async render() {
    try {
      // Try to get full product details
      const product = await this.getProductDetails();
      this.renderFullProductPage(product);
    } catch (error) {
      console.error('Failed to load full product details:', error);
      
      try {
        // Try to get product from cache
        const cachedProduct = this.getFromCache();
        if (cachedProduct) {
          this.renderFullProductPage(cachedProduct);
          this.showStaleDataNotification();
          return;
        }
      } catch (cacheError) {
        console.error('Cache retrieval failed:', cacheError);
      }
      
      try {
        // Try to get basic product info
        const basicProduct = await this.getBasicProductInfo();
        this.renderBasicProductPage(basicProduct);
        return;
      } catch (basicError) {
        console.error('Basic product info failed:', basicError);
      }
      
      // Last resort - show generic product page
      this.renderGenericErrorPage();
    }
  }
  
  async getProductDetails() {
    const response = await fetch(`/api/products/${this.productId}?full=true`);
    if (!response.ok) throw new Error('Failed to fetch product details');
    
    const product = await response.json();
    this.saveToCache(product);
    return product;
  }
  
  async getBasicProductInfo() {
    // Simplified API call with fewer details
    const response = await fetch(`/api/products/${this.productId}/basic`);
    if (!response.ok) throw new Error('Failed to fetch basic product info');
    return response.json();
  }
  
  getFromCache() {
    const cached = localStorage.getItem(this.cacheKey);
    if (!cached) return null;
    
    const { timestamp, data } = JSON.parse(cached);
    if (Date.now() - timestamp > this.cacheExpiry) {
      // Cache expired
      return null;
    }
    
    return data;
  }
  
  saveToCache(product) {
    const cacheData = {
      timestamp: Date.now(),
      data: product
    };
    localStorage.setItem(this.cacheKey, JSON.stringify(cacheData));
  }
}

Fallback Strategies:

  • Static content fallbacks
  • Default responses
  • Cached data
  • Simplified algorithms
  • Alternative services
  • Degraded functionality
  • Asynchronous processing

Testing for Resilience