Introduction
PHP OPcache stores precompiled script bytecode in shared memory to avoid parsing and compiling PHP files on every request. When the shared memory pool fills up (opcache.memory_consumption default is 128MB), OPcache stops caching new files and logs OPcache cache is full warnings. This means frequently accessed files are not cached, causing performance degradation. The fix requires sizing the OPcache memory pool based on the total size of compiled PHP files, monitoring cache usage to identify when tuning is needed, and configuring proper cache invalidation for deployments.
Symptoms
PHP error log:
[09-Apr-2026 10:00:00 UTC] PHP Warning: OPcache cache is full in Unknown on line 0Or performance degradation:
# Before cache full: average response time 50ms
# After cache full: average response time 200ms
# Because PHP files are being re-compiled on every requestCache status:
$status = opcache_get_status();
echo "Memory used: " . $status['memory_usage']['used_memory'] . "\n";
echo "Memory free: " . $status['memory_usage']['free_memory'] . "\n";
echo "Cached scripts: " . $status['opcache_statistics']['num_cached_scripts'] . "\n";
// free_memory = 0, cache is fullCommon Causes
- opcache.memory_consumption too small: Default 128MB insufficient for large codebase
- Too many files cached: Large framework with many files exceeds cache capacity
- opcache.max_accelerated_files too low: Default 10000 files not enough
- Frequent deployments: Cache reset on every deploy, never reaching optimal state
- Development mode enabled: opcache.validate_timestamps=1 causes unnecessary revalidation
- String intern buffer full: Large number of unique strings in cached scripts
Step-by-Step Fix
Step 1: Configure OPcache for production
```ini ; php.ini or /etc/php/8.2/fpm/conf.d/10-opcache.ini opcache.enable=1 opcache.enable_cli=1
; Increase memory based on your codebase size opcache.memory_consumption=512 ; MB - increase from default 128
; Maximum number of files to cache opcache.max_accelerated_files=20000 ; Increase from default 10000
; Revalidation settings opcache.validate_timestamps=0 ; 0 for production (manual reset only) opcache.revalidate_freq=0 ; Not used when validate_timestamps=0
; String optimization opcache.interned_strings_buffer=32 ; MB for string deduplication opcache.save_comments=1 ; Keep docblock annotations (needed for frameworks)
; Optimization opcache.fast_shutdown=1 opcache.enable_file_override=0 ; Enable only if validate_timestamps=0 opcache.optimization_level=0x7FFFBFFF ```
Step 2: Monitor OPcache usage
```php <?php // opcache-status.php - protected admin endpoint $status = opcache_get_status(false); $memory = $status['memory_usage']; $stats = $status['opcache_statistics'];
$usagePercent = ($memory['total_memory'] > 0) ? ($memory['used_memory'] / $memory['total_memory'] * 100) : 0;
echo json_encode([ 'memory_used_mb' => round($memory['used_memory'] / 1024 / 1024, 1), 'memory_total_mb' => round($memory['total_memory'] / 1024 / 1024, 1), 'memory_usage_percent' => round($usagePercent, 1), 'cached_scripts' => $stats['num_cached_scripts'], 'max_cached_scripts' => ini_get('opcache.max_accelerated_files'), 'hits' => $stats['hits'], 'misses' => $stats['misses'], 'hit_rate' => round($stats['opcache_hit_rate'], 2) . '%', ]); ```
Step 3: Reset cache after deployment
```bash #!/bin/bash # deploy.sh - reset OPcache after deploying new code
# Deploy new code git pull origin main
# Reset OPcache (must be done via PHP-FPM) # Option 1: Restart PHP-FPM (simplest) systemctl reload php8.2-fpm
# Option 2: Use opcache_reset() via PHP CLI (PHP 7.0+) php -r 'if (function_exists("opcache_reset")) { opcache_reset(); echo "OPcache reset\n"; }'
# Verify cache is rebuilding sleep 5 curl -s http://localhost/opcache-status.php ```
Prevention
- Size opcache.memory_consumption to exceed total compiled PHP file size
- Set opcache.max_accelerated_files to exceed total PHP files in project
- Disable opcache.validate_timestamps in production for maximum performance
- Reset OPcache after every code deployment
- Monitor cache hit rate -- should be above 99% in production
- Use opcache_compile_file() in warmup scripts to pre-populate cache
- Add OPcache status monitoring to your application health checks