Skip to main content
Back to ScopeForged

ScopeForged Documentation

Technical documentation, guides, and feature references for the ScopeForged client portal.

System & Infrastructure/Performance & Caching

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

  1. Cache Dashboard
  2. Cache Configuration
  3. Caching Strategies
  4. Cache Management
  5. Query Optimization
  6. Technical Architecture
  7. 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

ServicePurpose
CacheMonitorServiceStats, hit rates, key info, alerts
CacheManagerServiceClear, invalidate, warmup
CacheWarmerServiceWarming strategies
CacheAnalyticsServiceInsights, recommendations
PerformanceCollectorRequest performance metrics

Cache Configuration

Cache Drivers

DriverUse CaseSpeed
fileDefault, simpleModerate
redisProduction recommendedFast
memcachedHigh-traffic sitesFast
databaseFallback optionSlow
arrayTesting onlyIn-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 TypeTTLReason
Dashboard stats5 minFrequently viewed
User permissions15 minSecurity balance
Analytics data1 hourExpensive queries
ConfigurationForeverRarely changes
Search results10 minFresh 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

TechniqueImplementation
Asset versioningVite handles automatically
Image optimizationUse appropriate formats
Lazy loadingLoad images on scroll
Code splittingVite dynamic imports

Database Optimization

TechniqueBenefit
IndexesFaster queries
Eager loadingReduce N+1
Query cachingAvoid repeated queries
Connection poolingFaster connections

Application Optimization

TechniqueBenefit
Route cachingFaster routing
Config cachingFaster boot
View cachingFaster rendering
Autoloader optimizationFaster 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

MetricTarget
Page load time< 2 seconds
Time to first byte< 500ms
Database queries< 20 per page
Memory usage< 128MB

Dependencies

FeatureRelationship
Admin ToolsCache management
Background JobsCache warming

Complementary Features

FeatureDescription
AnalyticsCached analytics
ReportsCached reports
Admin DashboardCached stats

Best Practices

For Caching

  1. Cache expensive operations not everything
  2. Use appropriate TTLs based on data volatility
  3. Invalidate proactively on data changes
  4. Use tags for organized invalidation
  5. Monitor cache hit rates

For Performance

  1. Profile before optimizing
  2. Index frequently queried columns
  3. Use eager loading for relationships
  4. Paginate large datasets
  5. Optimize images and assets

Troubleshooting

IssueSolution
Stale cache dataCheck invalidation logic
Cache not workingVerify driver config
Memory issuesReduce cache TTL or size
Slow queriesAdd indexes, use caching

See Also