| ← 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:
permissions_structurebranch_structuremember_permissions(viamember_securitygroup)
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:
- Cache TTL reduced to +2 minutes for all stores
- Allows rapid testing of cache clearing behavior
- Useful for verifying cache behavior during development
This prevents cached data from blocking code changes during development while maintaining cache functionality.
Performance Characteristics
APCu Advantages:
- In-process memory caching (no network overhead)
- Extremely fast access times (microseconds)
- No serialization needed (PHP objects cached directly)
- Ideal for shared-memory setups
APCu Limitations:
- Not shared between separate PHP processes (e.g., multiple servers)
- Cleared on PHP-FPM restart
- Limited by available memory
- Not suitable for distributed caching
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:
- Development: Cache expires in 2 minutes when
DEBUG=true - Production: Cache expires at configured TTL (1-999 days)
- Manual invalidation: Use
Cache::delete()orCache::clearGroup()
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
- Short TTL (5-30 min): Permission data, user preferences
- Medium TTL (1 hour): General application data
- Long TTL (999 days): Structural data (roles, branches, permissions hierarchy)
2. Cache Invalidation Strategy
- On-demand invalidation: For permission/role changes
- TTL expiration: For general data
- Group invalidation: For related data changes
3. Development Workflow
- Use
DEBUG=trueto force 2-minute cache TTL during development - Clear cache frequently:
bin/cake cache clear_all - Test cache clearing after making changes
4. Performance Tuning
- Profile cache hits vs. misses
- Monitor APCu memory usage
- Consider Redis for distributed systems
- Review slow queries in
logs/queries.log
5. Security Considerations
- Cache invalidation is critical after permission changes
- Clear member permissions immediately after modifications
- Avoid caching sensitive data unnecessarily
- Cache permissions, not sensitive member data
6. Production Deployment
- Pre-warm caches after deployment
- Monitor cache hit rates
- Set up alerts for cache invalidation failures
- Consider dedicated cache servers for high traffic
Troubleshooting Cache Issues
Cache Not Working
- Verify APCu installed:
php -m | grep apcu - Check cache configuration: Verify cache store is enabled
- Clear cache:
bin/cake cache clear_all - Check permissions: Ensure PHP process can access cache
Stale Data
- Check TTL: Verify cache expiration is appropriate
- Verify invalidation: Check if cache is cleared after updates
- Debug cache hits: Enable query logging to see cache effectiveness
High Memory Usage
- Reduce cache TTL: Allow faster expiration
- Monitor cache size: Check APCu statistics
- Switch backends: Consider Redis with TTL management
- Clear manually:
bin/cake cache clear_all
Permission Changes Not Reflected
- Clear member security group:
Cache::clearGroup('member_security') - Clear full security group:
Cache::clearGroup('security') - Restart PHP-FPM: Clears all APCu caches