Performance Optimization & Caching Guide
Last Updated: 2026-01-12 Status: Implemented (Enhanced) Plan Reference: 061-performance-caching-enhancement.md
Overview
The Performance & Caching system optimizes application speed through strategic caching, query optimization, and resource management. It includes application caching, database query caching, view caching, and performance monitoring tools.
Table of Contents
- Cache Dashboard
- Cache Configuration
- Caching Strategies
- Cache Management
- Query Optimization
- Technical Architecture
- Related Features
Cache Dashboard
Access
- Navigation: More > Cache Dashboard
- URL:
/admin/cache - Permissions: Admin only
Dashboard Views
Main Dashboard (/admin/cache)
Overview of cache health with stats for driver, hit rate, memory usage, keys count, top accessed keys, and alerts.
Cache Management (/admin/cache/manage)
- Quick actions: Clear all, views, config, routes
- Pattern-based clearing (e.g.,
users:*) - Tag-based clearing
- Cache warmup strategies
Performance Metrics (/admin/cache/performance)
- Real-time stats: response time, requests/hour, hit rate, memory
- Database performance: avg queries, slow queries, N+1 detection
- Slow requests log with URL, method, duration, query count
Analytics (/admin/cache/analytics)
- Summary: total accesses, hits/misses, unique keys
- AI recommendations for optimization
- Caching opportunities (slow endpoints)
- Cache waste detection
- Hourly access patterns
Console Commands
# Warm all cache strategies
php artisan cache:warm
# Warm specific strategy
php artisan cache:warm --strategy=dashboard
# List available strategies
php artisan cache:warm --list
Services
| Service | Purpose |
|---|---|
CacheMonitorService | Stats, hit rates, key info, alerts |
CacheManagerService | Clear, invalidate, warmup |
CacheWarmerService | Warming strategies |
CacheAnalyticsService | Insights, recommendations |
PerformanceCollector | Request performance metrics |
Cache Configuration
Cache Drivers
| Driver | Use Case | Speed |
|---|---|---|
file | Default, simple | Moderate |
redis | Production recommended | Fast |
memcached | High-traffic sites | Fast |
database | Fallback option | Slow |
array | Testing only | In-memory |
Environment Setup
CACHE_DRIVER=redis
CACHE_PREFIX=portal_
# Redis configuration
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_CACHE_DB=1
Cache Configuration
// config/cache.php
'default' => env('CACHE_DRIVER', 'file'),
'stores' => [
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
'lock_connection' => 'default',
],
],
'prefix' => env('CACHE_PREFIX', 'laravel_cache_'),
Caching Strategies
Data Caching
Dashboard Statistics:
$stats = Cache::remember('dashboard:stats', 300, function () {
return [
'total_clients' => Client::count(),
'active_projects' => Project::active()->count(),
'revenue_mtd' => Invoice::paidThisMonth()->sum('total'),
];
});
User-Specific Data:
$projects = Cache::tags(['user', "user:{$user->id}"])
->remember("user:{$user->id}:projects", 600, function () use ($user) {
return $user->accessibleProjects()->with('client')->get();
});
Configuration Caching:
$settings = Cache::rememberForever('app:settings', function () {
return Setting::all()->pluck('value', 'key');
});
Query Result Caching
// Cache expensive queries
$topClients = Cache::remember('analytics:top_clients', 3600, function () {
return Client::withSum('invoices', 'total')
->orderByDesc('invoices_sum_total')
->limit(10)
->get();
});
View Caching
# Cache compiled Blade views
php artisan view:cache
# Clear view cache
php artisan view:clear
Route Caching
# Cache routes (production only)
php artisan route:cache
# Clear route cache
php artisan route:clear
Config Caching
# Cache configuration
php artisan config:cache
# Clear config cache
php artisan config:clear
Cache Management
Cache Tags
Organize cache entries for selective invalidation:
// Store with tags
Cache::tags(['clients', 'statistics'])->put('client:count', $count, 3600);
// Flush by tag
Cache::tags(['clients'])->flush();
Cache Invalidation
Model Observer:
class ClientObserver
{
public function saved(Client $client): void
{
Cache::tags(['clients'])->flush();
Cache::forget('dashboard:stats');
}
public function deleted(Client $client): void
{
Cache::tags(['clients', "client:{$client->id}"])->flush();
}
}
Event-Based Invalidation:
Event::listen(InvoicePaid::class, function ($event) {
Cache::forget('dashboard:stats');
Cache::tags(['invoices', 'analytics'])->flush();
});
TTL Guidelines
| Data Type | TTL | Reason |
|---|---|---|
| Dashboard stats | 5 min | Frequently viewed |
| User permissions | 15 min | Security balance |
| Analytics data | 1 hour | Expensive queries |
| Configuration | Forever | Rarely changes |
| Search results | 10 min | Fresh results |
Query Optimization
Eager Loading
// Bad - N+1 queries
$projects = Project::all();
foreach ($projects as $project) {
echo $project->client->name; // Query per project
}
// Good - Single query
$projects = Project::with('client')->get();
foreach ($projects as $project) {
echo $project->client->name; // No additional queries
}
Query Scopes
// In Model
public function scopeWithStats($query)
{
return $query
->withCount('projects')
->withSum('invoices', 'total');
}
// Usage
$clients = Client::withStats()->get();
Chunking Large Results
// Process large datasets efficiently
Client::chunk(100, function ($clients) {
foreach ($clients as $client) {
$this->processClient($client);
}
});
Database Indexing
// Migration
Schema::table('invoices', function (Blueprint $table) {
$table->index(['client_id', 'status']);
$table->index(['created_at', 'status']);
$table->index('due_date');
});
Technical Architecture
Cache Service
Location: app/Services/CacheService.php
class CacheService
{
public function getDashboardStats(): array
{
return Cache::remember('dashboard:stats', 300, fn() => [
'clients' => Client::count(),
'projects' => Project::active()->count(),
'revenue' => Invoice::paid()->sum('total'),
]);
}
public function invalidateDashboard(): void
{
Cache::forget('dashboard:stats');
}
public function warmCache(): void
{
$this->getDashboardStats();
$this->getTopClients();
$this->getRecentActivity();
}
}
Cache Middleware
// Cache entire responses
class CacheResponse
{
public function handle($request, Closure $next, $ttl = 60)
{
$key = 'response:' . sha1($request->fullUrl());
return Cache::remember($key, $ttl, function () use ($next, $request) {
return $next($request);
});
}
}
Performance Monitoring
// Log slow queries
DB::listen(function ($query) {
if ($query->time > 100) { // > 100ms
Log::warning('Slow query detected', [
'sql' => $query->sql,
'time' => $query->time,
'bindings' => $query->bindings,
]);
}
});
Artisan Commands
# Clear all caches
php artisan cache:clear
# Optimize for production
php artisan optimize
# Clear optimization
php artisan optimize:clear
# Warm caches
php artisan cache:warm
Cache Warming Job
class WarmCacheJob implements ShouldQueue
{
public function handle(CacheService $cache): void
{
$cache->warmCache();
}
}
// Schedule
$schedule->job(new WarmCacheJob)->hourly();
Performance Tips
Frontend Optimization
| Technique | Implementation |
|---|---|
| Asset versioning | Vite handles automatically |
| Image optimization | Use appropriate formats |
| Lazy loading | Load images on scroll |
| Code splitting | Vite dynamic imports |
Database Optimization
| Technique | Benefit |
|---|---|
| Indexes | Faster queries |
| Eager loading | Reduce N+1 |
| Query caching | Avoid repeated queries |
| Connection pooling | Faster connections |
Application Optimization
| Technique | Benefit |
|---|---|
| Route caching | Faster routing |
| Config caching | Faster boot |
| View caching | Faster rendering |
| Autoloader optimization | Faster class loading |
Monitoring Performance
Built-in Tools
// Query count debugging
DB::enableQueryLog();
// ... code ...
dd(DB::getQueryLog());
Laravel Debugbar (Development)
composer require barryvdh/laravel-debugbar --dev
Performance Metrics
| Metric | Target |
|---|---|
| Page load time | < 2 seconds |
| Time to first byte | < 500ms |
| Database queries | < 20 per page |
| Memory usage | < 128MB |
Related Features
Dependencies
| Feature | Relationship |
|---|---|
| Admin Tools | Cache management |
| Background Jobs | Cache warming |
Complementary Features
| Feature | Description |
|---|---|
| Analytics | Cached analytics |
| Reports | Cached reports |
| Admin Dashboard | Cached stats |
Best Practices
For Caching
- Cache expensive operations not everything
- Use appropriate TTLs based on data volatility
- Invalidate proactively on data changes
- Use tags for organized invalidation
- Monitor cache hit rates
For Performance
- Profile before optimizing
- Index frequently queried columns
- Use eager loading for relationships
- Paginate large datasets
- Optimize images and assets
Troubleshooting
| Issue | Solution |
|---|---|
| Stale cache data | Check invalidation logic |
| Cache not working | Verify driver config |
| Memory issues | Reduce cache TTL or size |
| Slow queries | Add indexes, use caching |
See Also
- Admin Tools - Cache management
- Background Jobs - Async processing
- Analytics - Cached analytics