Skip to content

iazaran/smart-cache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Laravel SmartCache - Optimize Caching for Large Data

Latest Version License PHP Version Tests

SmartCache optimizes Laravel caching for large datasets through intelligent compression (up to 70% size reduction), smart chunking, and automatic optimization - while maintaining Laravel's familiar Cache API.

🎯 The Problem It Solves

Caching large datasets (10K+ records, API responses, reports) in Laravel can cause:

  • Memory issues - Large arrays consume too much RAM
  • Storage waste - Uncompressed data fills Redis/Memcached quickly
  • Slow performance - Serializing/deserializing huge objects takes time
  • Cache stampede - Multiple processes regenerating expensive data simultaneously

SmartCache fixes all of this automatically.

πŸ“¦ Installation

composer require iazaran/smart-cache

That's it! Works out-of-the-box. No configuration required.

Requirements:

  • PHP 8.1+
  • Laravel 8.0 - 12.x
  • Any cache driver (Redis, File, Database, Memcached, Array)

πŸš€ Quick Start

Drop-in Replacement

Use exactly like Laravel's Cache facade:

use SmartCache\Facades\SmartCache;

// Works exactly like Laravel Cache
SmartCache::put('users', $users, 3600);
$users = SmartCache::get('users');

// Remember pattern
$users = SmartCache::remember('users', 3600, function() {
    return User::all();
});

✨ The Magic: Large data is automatically compressed and chunked - reducing cache size by up to 70%!

Helper Function

// Store
smart_cache(['products' => $products], 3600);

// Retrieve
$products = smart_cache('products');

πŸ’‘ Core Features (Automatic Optimization)

1. Intelligent Compression

Large data is automatically compressed:

// Large API response - automatically compressed
$apiData = Http::get('api.example.com/large-dataset')->json();
SmartCache::put('api_data', $apiData, 3600);
// Automatically compressed with gzip, saving up to 70% space

When it applies: Data > 50KB (configurable) Benefit: 60-80% size reduction

2. Smart Chunking

Large arrays are automatically split into manageable chunks:

// 10,000+ records - automatically chunked
$users = User::with('profile', 'posts')->get();
SmartCache::put('all_users', $users, 3600);
// Automatically split into 1000-item chunks

When it applies: Arrays with 5000+ items (configurable) Benefit: Better memory usage, faster access

3. Automatic Strategy Selection

SmartCache chooses the best optimization automatically:

Data Type Size Strategy Benefit
Large Arrays (5000+ items) Any Chunking Better memory, faster access
Text/Strings >50KB Compression 60-80% size reduction
Mixed Objects >50KB Compression Optimal serialization
API Responses >100KB Both Best performance
Small Data <50KB None Fastest (no overhead)

πŸ“ˆ Real Performance Impact

Production Results (E-commerce Platform):

  • 72% cache size reduction (15MB β†’ 4.2MB)
  • 800MB daily Redis memory savings
  • 40% faster retrieval vs standard Laravel Cache
  • 94.3% cache hit ratio
  • 23ms average retrieval time

πŸ”§ Advanced Features (Opt-in)

All advanced features are opt-in and disabled by default for maximum compatibility.

πŸ”’ Atomic Locks - Prevent Cache Stampede

Prevent multiple processes from regenerating expensive cache simultaneously:

$lock = SmartCache::lock('expensive_operation', 10);

if ($lock->get()) {
    // Only one process executes this
    $data = expensiveApiCall();
    SmartCache::put('api_data', $data, 3600);
    $lock->release();
}

// Or use callback pattern
SmartCache::lock('regenerate_cache', 30)->get(function() {
    return regenerateExpensiveData();
});

Benefit: Prevents cache stampede, reduces server load

⚑ Cache Memoization - 10-100x Faster

Cache data in memory for the current request:

$memo = SmartCache::memo();

// First call hits cache, subsequent calls are instant
$users = $memo->remember('users', 3600, fn() => User::all());
$users = $memo->get('users'); // Instant! (from memory)
$users = $memo->get('users'); // Still instant!

// Perfect for loops
foreach ($products as $product) {
    $category = $memo->get("category_{$product->category_id}");
}

Benefit: 10-100x faster repeated access within same request/job

πŸ”’ Batch Operations

Optimize multiple cache operations:

// Retrieve multiple keys
$values = SmartCache::many(['key1', 'key2', 'key3']);

// Store multiple keys
SmartCache::putMany([
    'key1' => 'value1',
    'key2' => 'value2',
], 3600);

// Delete multiple keys
SmartCache::deleteMultiple(['key1', 'key2', 'key3']);

🎯 Adaptive Compression

Auto-optimize compression levels based on data characteristics:

// Enable in config
config(['smart-cache.strategies.compression.mode' => 'adaptive']);

// Automatically selects optimal level:
SmartCache::put('hot_data', $frequentlyAccessed, 3600);  // Level 3-4 (faster)
SmartCache::put('cold_data', $rarelyAccessed, 3600);     // Level 7-9 (smaller)

How it works:

  • Analyzes data compressibility
  • Tracks access frequency
  • Hot data = faster compression
  • Cold data = higher compression

πŸ’Ύ Lazy Loading

Load large datasets on-demand to save memory:

// Enable in config
config(['smart-cache.strategies.chunking.lazy_loading' => true]);

// Returns LazyChunkedCollection
$largeDataset = SmartCache::get('100k_records');

// Chunks loaded on-demand (max 3 in memory)
foreach ($largeDataset as $record) {
    processRecord($record);
}

// Access specific items
$item = $largeDataset[50000]; // Only loads needed chunk

Benefit: 30-50% memory savings for large datasets

🧠 Smart Serialization

Auto-select best serialization method:

// Automatically chooses:
SmartCache::put('simple', ['key' => 'value'], 3600);  // JSON (fastest)
SmartCache::put('complex', $objectGraph, 3600);       // igbinary/PHP

Methods: JSON β†’ igbinary (if available) β†’ PHP serialize

πŸ“‘ Cache Events

Monitor cache operations in real-time:

// Enable in config
config(['smart-cache.events.enabled' => true]);

// Listen to events
Event::listen(CacheHit::class, fn($e) => Log::info("Hit: {$e->key}"));
Event::listen(CacheMissed::class, fn($e) => Log::warning("Miss: {$e->key}"));
Event::listen(OptimizationApplied::class, fn($e) =>
    Log::info("Optimized {$e->key}: {$e->ratio}% reduction")
);

Events: CacheHit, CacheMissed, KeyWritten, KeyForgotten, OptimizationApplied

πŸ” Encryption Strategy

Encrypt sensitive cached data automatically:

// Enable in config
config(['smart-cache.encryption.enabled' => true]);
config(['smart-cache.encryption.keys' => ['user_*', 'payment_*']]);

// Sensitive data is automatically encrypted
SmartCache::put('user_123_ssn', $sensitiveData, 3600);
// Data encrypted at rest, decrypted on retrieval

Benefit: Secure sensitive data in cache without code changes

🏷️ Cache Namespacing

Group and manage cache keys by namespace:

// Set namespace for operations
SmartCache::namespace('users')->put('profile', $data, 3600);
SmartCache::namespace('users')->put('settings', $settings, 3600);

// Flush entire namespace
SmartCache::flushNamespace('users'); // Clears all user:* keys

// Get all keys in namespace
$keys = SmartCache::getNamespaceKeys('users');

Benefit: Organize cache keys, easy bulk invalidation

⏱️ TTL Jitter

Prevent thundering herd with randomized TTL:

// Add 10% jitter to TTL
SmartCache::withJitter(0.1)->put('popular_data', $data, 3600);
// Actual TTL: 3240-3960 seconds (Β±10%)

// Or use dedicated methods
SmartCache::putWithJitter('key', $value, 3600, 0.15); // 15% jitter
SmartCache::rememberWithJitter('key', 3600, 0.1, fn() => expensiveCall());

Benefit: Prevents cache stampede when many keys expire simultaneously

πŸ”Œ Circuit Breaker

Auto-fallback when cache backend fails:

// Check if cache is available
if (SmartCache::isAvailable()) {
    $data = SmartCache::get('key');
}

// Execute with automatic fallback
$data = SmartCache::withFallback(
    fn() => SmartCache::get('key'),           // Primary
    fn() => Database::query('SELECT ...')     // Fallback
);

// Get circuit breaker stats
$stats = SmartCache::getCircuitBreakerStats();
// Returns: state, failure_count, success_count, last_failure_at

States: Closed (normal) β†’ Open (failing) β†’ Half-Open (testing)

🚦 Rate Limiting & Stampede Protection

Prevent cache stampede with rate limiting:

// Throttle cache operations
$result = SmartCache::throttle('api_call', 10, 60, function() {
    return expensiveApiCall();
}); // Max 10 calls per 60 seconds

// Remember with stampede protection (XFetch algorithm)
$data = SmartCache::rememberWithStampedeProtection('key', 3600, function() {
    return expensiveComputation();
});

Benefit: Prevents multiple processes from regenerating cache simultaneously

πŸ”₯ Cache Warming

Pre-warm cache with artisan command:

# Warm cache using registered warmers
php artisan smart-cache:warm

# Warm specific warmer
php artisan smart-cache:warm --warmer=ProductCacheWarmer

Register warmers in your service provider:

use SmartCache\Contracts\CacheWarmer;

class ProductCacheWarmer implements CacheWarmer
{
    public function warm(): void
    {
        $products = Product::all();
        SmartCache::put('all_products', $products, 3600);
    }

    public function getKey(): string
    {
        return 'products';
    }
}

// Register in AppServiceProvider
$this->app->tag([ProductCacheWarmer::class], 'smart-cache.warmers');

🧹 Orphan Chunk Cleanup

Automatically clean up orphan chunks:

# Clean up orphan chunks
php artisan smart-cache:cleanup-chunks

# Dry run (show what would be cleaned)
php artisan smart-cache:cleanup-chunks --dry-run

πŸ“Š Cache Statistics Dashboard

View cache statistics via web interface:

// Enable in config
config(['smart-cache.dashboard.enabled' => true]);
config(['smart-cache.dashboard.prefix' => 'smart-cache']);
config(['smart-cache.dashboard.middleware' => ['web', 'auth']]);

Routes:

  • GET /smart-cache/dashboard - HTML dashboard
  • GET /smart-cache/statistics - JSON statistics
  • GET /smart-cache/health - Health check
  • GET /smart-cache/keys - Managed keys list

🌊 Modern Patterns (Laravel 12+)

SWR (Stale-While-Revalidate)

Serve stale data while refreshing in background:

$apiData = SmartCache::swr('github_repos', function() {
    return Http::get('https://api.github.com/user/repos')->json();
}, 300, 900); // 5min fresh, 15min stale

Extended Stale Serving

For slowly changing data:

$siteConfig = SmartCache::stale('site_config', function() {
    return Config::fromDatabase();
}, 3600, 86400); // 1hour fresh, 24hour stale

Refresh-Ahead

Proactively refresh before expiration:

$analytics = SmartCache::refreshAhead('daily_analytics', function() {
    return Analytics::generateReport();
}, 1800, 300); // 30min TTL, 5min refresh window

Smart Invalidation

Pattern-based cache clearing:

// Clear by pattern
SmartCache::flushPatterns([
    'user_*',           // All user keys
    'api_v2_*',         // All API v2 cache
    '/product_\d+/'     // Regex: product_123, product_456
]);

// Dependency tracking
SmartCache::dependsOn('user_posts', 'user_profile');
SmartCache::invalidate('user_profile'); // Also clears user_posts

πŸ“Š Monitoring & Management

Performance Metrics

$metrics = SmartCache::getPerformanceMetrics();
// Returns: hit_ratio, compression_savings, operation_timing, etc.

$analysis = SmartCache::analyzePerformance();
// Returns: health score, recommendations, issues

CLI Commands

# Status overview
php artisan smart-cache:status

# Detailed analysis
php artisan smart-cache:status --force

# Clear cache
php artisan smart-cache:clear
php artisan smart-cache:clear expensive_api_call

HTTP Management

Execute commands via web interface (no SSH needed):

$status = SmartCache::executeCommand('status');
$clearResult = SmartCache::executeCommand('clear', ['key' => 'api_data']);

βš™οΈ Configuration

Publish Config (Optional)

php artisan vendor:publish --tag=smart-cache-config

Key Configuration Options

// config/smart-cache.php
return [
    // Size thresholds for optimization
    'thresholds' => [
        'compression' => 1024 * 50,  // 50KB - compress data larger than this
        'chunking' => 1024 * 100,    // 100KB - chunk arrays larger than this
    ],

    // Optimization strategies
    'strategies' => [
        'compression' => [
            'enabled' => true,
            'mode' => 'fixed',       // 'fixed' or 'adaptive'
            'level' => 6,            // 1-9 (higher = better compression)
        ],
        'chunking' => [
            'enabled' => true,
            'chunk_size' => 1000,    // Items per chunk
            'lazy_loading' => false, // Enable for memory savings
            'smart_sizing' => false, // Auto-calculate chunk size
        ],
    ],

    // Events (disabled by default for performance)
    'events' => [
        'enabled' => false,
    ],

    // Performance monitoring
    'monitoring' => [
        'enabled' => true,
        'metrics_ttl' => 3600,
    ],

    // Encryption for sensitive data
    'encryption' => [
        'enabled' => false,
        'keys' => [],              // Keys to encrypt: ['user_*', 'payment_*']
        'patterns' => [],          // Regex patterns: ['/secret_.*/']
    ],

    // Circuit breaker for cache backend failures
    'circuit_breaker' => [
        'enabled' => true,
        'failure_threshold' => 5,  // Failures before opening
        'success_threshold' => 2,  // Successes to close
        'timeout' => 30,           // Seconds before half-open
    ],

    // Rate limiting for cache operations
    'rate_limiter' => [
        'enabled' => true,
        'default_limit' => 100,    // Max operations per window
        'window' => 60,            // Window in seconds
    ],

    // TTL jitter to prevent thundering herd
    'jitter' => [
        'enabled' => false,
        'percentage' => 0.1,       // 10% jitter by default
    ],

    // Statistics dashboard
    'dashboard' => [
        'enabled' => false,
        'prefix' => 'smart-cache',
        'middleware' => ['web'],
    ],
];

πŸ”§ Supported Cache Drivers

Driver Compression Chunking Locks All Features
Redis βœ… βœ… βœ… βœ… Full Support
File βœ… βœ… βœ… βœ… Full Support
Database βœ… βœ… βœ… βœ… Full Support
Array βœ… βœ… βœ… βœ… Full Support
Memcached βœ… βœ… βœ… βœ… Full Support

All Laravel cache drivers are fully supported!

πŸš€ Migration from Laravel Cache

SmartCache is a drop-in replacement - your existing code works unchanged:

// Before (Laravel Cache)
use Illuminate\Support\Facades\Cache;

Cache::put('users', $users, 3600);
$users = Cache::get('users');

// After (SmartCache) - just change the import
use SmartCache\Facades\SmartCache;

SmartCache::put('users', $users, 3600);  // Now automatically optimized!
$users = SmartCache::get('users');       // Automatically restored!

That's it! No code changes needed. You immediately get:

  • βœ… Automatic compression for large data
  • βœ… Smart chunking for large arrays
  • βœ… All new features available

πŸ“š Documentation

πŸ“– Full Documentation - Complete guide with examples

Quick Links

πŸ§ͺ Testing

SmartCache includes 300+ comprehensive tests covering all functionality:

composer test

# With coverage
composer test-coverage

🀝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

πŸ“„ License

MIT License. See LICENSE for details.

πŸ”— Links


Built with ❀️ for the Laravel community

Optimize caching for large data - from simple apps to enterprise systems