Skip to the content.
← Back to Services ← Back to Table of Contents

6.4 Caching Strategy

Last Updated: December 3, 2025

This document explains the KMP caching architecture, configuration, and best practices for application performance and data consistency.

Overview

KMP implements a multi-tier caching strategy using APCu (Alternative PHP Cache User Cache) for high-performance, in-memory caching. This approach significantly reduces database queries and improves application response times.

Cache Architecture

Cache Tiers

KMP uses multiple cache stores, each optimized for different data types:

Cache Store Purpose TTL Update Frequency
default General application data 1 hour On-demand
member_permissions User permission cache 30 minutes After permission changes
permissions_structure Role/permission hierarchy 999 days Rarely (structural)
branch_structure Organizational hierarchy 999 days Rarely (structural)
_cake_translations_ Compiled translation files 1 year On deployment
_cake_model_ Database schema metadata 1 year On schema changes

Cache Flow Diagram

Request
  ↓
  ├─→ Check Default Cache (1 hour)
  │    └─→ If missed: Query DB, cache result
  ├─→ Check Member Permissions Cache (30 min)
  │    └─→ If missed: Calculate perms, cache result
  ├─→ Check Permissions Structure Cache (999 days)
  │    └─→ If missed: Build structure, cache result
  └─→ Application Logic

Cache Configuration

APCu Engine Configuration

All cache stores use ApcuEngine for memory-based caching:

"Cache" => [
    "default" => [
        "className" => ApcuEngine::class,
        'duration' => '+1 hours',
    ],
    "member_permissions" => [
        "className" => ApcuEngine::class,
        "duration" => "+30 minutes",
        'groups' => ['security', 'member_security']
    ],
    // ... additional stores
]

Cache Stores

1. Default Cache

Purpose: General application data
TTL: 1 hour
Use: Non-critical caching of computed data

Cache::write('key', $value);                      // Uses 'default' store
Cache::read('key');                               // Reads from 'default'
Cache::delete('key');                             // Removes specific key

2. Member Permissions Cache

Purpose: Individual member permission data
TTL: 30 minutes
Groups: security, member_security

This cache stores pre-computed permission sets for each member, allowing fast authorization checks without database queries.

Auto-invalidation: Automatically cleared 30 minutes after last access or on permission changes.

Cache::write('member_perms_123', $permissions, 'member_permissions');
Cache::clearGroup('member_security');  // Clear on permission change

3. Permissions Structure Cache

Purpose: Role/permission hierarchy and relationships
TTL: 999 days (effectively permanent)
Groups: security

This cache stores the complete role and permission structure, which rarely changes. It should be manually cleared after security updates.

Cache::write('permissions_structure', $data, 'permissions_structure');
Cache::clearGroup('security');  // Clear all security caches

4. Branch Structure Cache

Purpose: Organizational hierarchy and branch relationships
TTL: 999 days (effectively permanent)
Groups: security

Similar to permissions structure, this cache stores organizational data that is relatively stable.

Cache::clearGroup('security');  // Clears both permissions and branch structure

5. Framework Caches

Translations (_cake_translations_): Compiled translation files for internationalization

Model Metadata (_cake_model_): Database schema descriptions and table listings

These are managed by CakePHP and typically don’t require manual intervention.

Cache Groups

Cache groups allow clearing related caches together without affecting other caches:

Security Group

Includes all security-related caches:

// Clear all security-related caches at once
Cache::clearGroup('security');

Affected caches:

Member Security Group

Member-specific security data:

Cache::clearGroup('member_security');  // Clear member permission caches

Cache Behavior

Debug Mode Impact

When DEBUG=true in development:

This prevents cached data from blocking code changes during development while maintaining cache functionality.

Performance Characteristics

APCu Advantages:

APCu Limitations:

Production Considerations

For high-availability deployments with multiple servers, consider alternative cache backends:

Redis Configuration:

# In environment variables or config/app_local.php
CACHE_CAKECORE_URL=redis://localhost:6379

Switching to Redis:

"Cache" => [
    "default" => [
        "className" => RedisEngine::class,
        "duration" => "+1 hours",
        "url" => env("CACHE_REDIS_URL", "redis://localhost:6379"),
    ],
]

Memcached Configuration:

Similar to Redis, configure via environment variables:

CACHE_MEMCACHED_URL=memcached://localhost:11211

Common Caching Patterns

Pattern 1: Check and Cache

// Check cache, compute if missing
$data = Cache::remember('my_key', function() {
    return expensiveOperation();
}, 'default');  // Uses 1-hour TTL

Pattern 2: Write and Invalidate

// Store computed result
Cache::write('computed_value', $result, 'default');

// Invalidate after data changes
Cache::delete('computed_value');

Pattern 3: Group-Based Invalidation

// Cache with group
Cache::write('user_prefs_123', $prefs, 'default');
Cache::setGroup('user_prefs_123', 'user_data');

// Clear all user-related caches
Cache::clearGroup('user_data');

Pattern 4: Permission Caching

// Cache member permissions
$perms = Cache::remember('member_perms_' . $memberId, 
    function() use ($memberId) {
        return calculateMemberPermissions($memberId);
    }, 
    'member_permissions'
);

// Invalidate on permission change
Cache::clearGroup('member_security');

Clearing Cache

Clear Specific Cache

# Clear a specific cache store
bin/cake cache clear default
bin/cake cache clear member_permissions

Clear by Group

# From PHP code
Cache::clearGroup('security');           // Clears permissions and branch caches
Cache::clearGroup('member_security');    // Clears member permission caches

Clear All Caches

# Clear all application caches
bin/cake cache clear_all

Automatic Cache Expiration

Caches automatically expire based on their configured TTL:

Monitoring Cache Performance

Check Cache Status

// Get cache configuration
$config = Cache::getConfig('default');
echo $config['duration'];  // Shows TTL

// Check if key exists
if (Cache::read('key')) {
    // Cache hit
} else {
    // Cache miss
}

APCu Status

From command line:

# Display APCu statistics
php -i | grep -A 20 "apc"

From web interface (install apcu_gui):

composer require --dev apcu/apcu_gui

Then access at http://localhost/apc.php

Cache Invalidation Strategy

Permission Changes

When member permissions are modified:

// After updating permissions
$this->Members->Permissions->updatePermissions($memberId, $newPerms);

// Invalidate permission caches
Cache::clearGroup('member_security');

Organization Structure Changes

When branch structure changes:

// After branch modifications
Cache::clearGroup('security');  // Clears branch + permissions caches

Role Definition Changes

When role permissions are modified:

// After role changes
Cache::clearGroup('security');  // Clears full security cache structure

Manual Cache Clearing

During development or troubleshooting:

# Clear all caches
bin/cake cache clear_all

# Clear specific cache
bin/cake cache clear member_permissions

Best Practices

1. Use Appropriate TTLs

2. Cache Invalidation Strategy

3. Development Workflow

4. Performance Tuning

5. Security Considerations

6. Production Deployment

Troubleshooting Cache Issues

Cache Not Working

  1. Verify APCu installed: php -m | grep apcu
  2. Check cache configuration: Verify cache store is enabled
  3. Clear cache: bin/cake cache clear_all
  4. Check permissions: Ensure PHP process can access cache

Stale Data

  1. Check TTL: Verify cache expiration is appropriate
  2. Verify invalidation: Check if cache is cleared after updates
  3. Debug cache hits: Enable query logging to see cache effectiveness

High Memory Usage

  1. Reduce cache TTL: Allow faster expiration
  2. Monitor cache size: Check APCu statistics
  3. Switch backends: Consider Redis with TTL management
  4. Clear manually: bin/cake cache clear_all

Permission Changes Not Reflected

  1. Clear member security group: Cache::clearGroup('member_security')
  2. Clear full security group: Cache::clearGroup('security')
  3. Restart PHP-FPM: Clears all APCu caches

See Also