The
{eac}ObjectCache is a light-weight and very efficient drop-in persistent object cache that uses a fast SQLite database and even faster APCu shared memory to cache WordPress objects.
See
The WordPress Object Cache
The WordPress Object Cache is used to save on trips to the database. The Object Cache stores all of the cache data to memory and makes the cache contents available by using a key, which is used to name and later retrieve the cache contents.
By default, the object cache is non-persistent. This means that data stored in the cache resides in memory only and only for the duration of the request. Cached data will not be stored persistently across page loads unless you install a persistent caching plugin.
Here, an object is any piece of data - a number, text, a set of database records, an API response, etc. - that can be referenced by a name or key. Objects are categorized by a group name. Groups help identify what an object is and how it is used.
{eac}ObjectCache replaces the default WordPress object cache to not only store data in process memory but to also store data persistently, across requests, in APCu shared memory and/or in a SQLite database, increasing the likelihood of cache hits and decreasing the need for costly computations, complex MySQL database queries, and remote API requests.
SQLite is a fast, small, single-file relational database engine. By using SQLite to store objects, {eac}ObjectCache is able to manage a relatively large amount of data (groups, keys, and values) in a very efficient and fast data-store.
APCu is a shared, in-memory, persistent cache available only when the
APCu PECL Extension is installed. {eac}ObjectCache uses APCu as an intermediate cache between the L1 memory cache and the L2 SQLite database cache providing extremely fast object retrieval,
{eac}ObjectCache always uses per-request, in-memory caching and may operate with either APCu memory caching or SQLite database caching - or both. APCu memory caching uses a single block of memory shared by all PHP requests and is persistent until and unless the cache is cleared or the server is rebooted (or PHP restarted). SQLite database caching is persistent until and unless the cache is deliberately cleared.
Features
- Lightweight, efficient, and fast!
- L1 (in-process memory) and L2 (APCu & SQLite) caching.
- Supports Write-Back (delayed transactions) or Write-Through SQL caching.
- Caching by object group name.
- Preserves uniqueness of keys.
- Manage keys by group name.
- Supports group name attributes (:sitewide, :nocaching, :permanent, :prefetch)
- Pre-fetch object groups from L2 to L1 cache.
- Caches and pre-fetches L2 misses (known to not exist in L2 cache).
- Prevents repeated, unnecessary L2 cache reads across requests.
- Multisite / Network support:
- Cache/flush/switch by blog id.
- Caching statistics:
- Cache hits (typically above 90%).
- Overall and L1/L2 hits, misses, & ratio.
- Cache hits by object groups.
- Number of APCu and SQLite keys stored.
- SQLite select/update/delete/commit counts.
- Supports an enhanced superset of WP Object Cache functions.
- Easily enabled or disabled from {eac}Doojigger administrator page.
- Imports existing MySQL transients.
- Exports cached transients to MySQL when disabled.
- Automatically cleans and optimizes SQLite database.
- Optionally schedule periodic cache invalidation and rebuild.
- Uses the PHP Data Objects (PDO) extension included with PHP.
While {eac}ObjectCache does support multiple WordPress installations on a single server it does not support multiple servers per installation. SQLite and APCu work only on a single server, not in a clustered or load-balanced environment.
Configuration Alternatives
Assuming you have SQLite and APCu installed, what are your best options?
-
Fastest Caching - Uses in-process memory and APCu shared memory.
-
Disable SQLite. *
define( 'EAC_OBJECT_CACHE_USE_DB', false );
- Advantage
- Fast memory-only access.
- Handles concurrent updates through APCu cache.
- Disadvantage
- APCu may invalidate data under memory constraint.
- APCu cache is not shared with CLI.
- APCu cache is lost on system or PHP restart.
-
Less memory (almost as fast) - Uses in-process memory and APCu shared memory.
-
Disable SQLite. *
define( 'EAC_OBJECT_CACHE_USE_DB', false );
- Optimize memory use. *
define( 'EAC_OBJECT_CACHE_OPTIMIZE_MEMORY', true );
- Advantage
- Fast memory-only access.
- Handles concurrent updates through APCu cache.
- Conserves per-request memory by not pushing APCu hits to in-process memory.
- Disadvantage
- Slightly slower to access APCu memory over in-process memory.
- APCu may invalidate data under memory constraint.
- APCu cache is not shared with CLI.
- APCu cache is lost on system or PHP restart.
-
Most resilient (and still fast) - Uses in-process memory, APCu shared memory, and SQLite database.
-
Do nothing, this is the default.
- Advantage
- Most cache hits will come from in-process and APCu memory.
- SQLite retains cache data after restart.
- Disadvantage
- Must keep SQLite database (on disk) updated.
- Potential concurrency issues on high-volume site.
-
Resilient, efficient, and fast (recommended) - Uses in-process memory, APCu shared memory, and SQLite database.
-
Optimize memory use. *
define( 'EAC_OBJECT_CACHE_OPTIMIZE_MEMORY', true );
- Advantage
- Most cache hits will come from in-process and APCu memory.
- Handles concurrent updates better through APCu cache.
- Conserves per-request memory by not pushing APCu hits to in-process memory.
- SQLite retains cache data after restart.
- Disadvantage
- Slightly slower to access APCu memory over in-process memory.
- Must keep SQLite database (on disk) updated.
-
Least efficient (default when APCu is not installed) - Uses in-process memory and SQLite database.
-
Disable APCu. *
define( 'EAC_OBJECT_CACHE_USE_APCU', false );
- Advantage
- Saves resources by not taking up APCu reserves.
- More secure by not using shared memory.
- SQLite retains cache data after restart.
- Disadvantage
- All cached data initially read from disk.
- Must keep SQLite database (on disk) updated.
- Potential concurrency issues on high-volume site.
- For high-volume sites - reduces or eliminates potential race conditions
- Optimize memory use. *
define( 'EAC_OBJECT_CACHE_OPTIMIZE_MEMORY', true );
- Disable delayed writes. *
define( 'EAC_OBJECT_CACHE_DELAYED_WRITES', false );
- Disable use of
alloptions array.
define( 'EAC_OBJECT_CACHE_DISABLE_ALLOPTIONS', true );
- Advantage
- Most cache hits will come from in-process and APCu memory.
- Conserves per-request memory by not pushing APCu hits to in-process memory.
- Updates SQLite data immediately.
- Conserves per-request memory by elimination large
alloptions array(s).
- Disadvantage
- Slightly slower to access APCu memory over in-process memory.
- Multiple single-row SQLite update transactions.
- Slightly slower to access individual options from cache rather than
alloptions array.
* These options may be set from the {eac}Doojigger administration screen.
When using SQLite, delayed writes (see below) dramatically improves efficiency by only writing updates at the end of the script process.
When using APCu shared memory, data is accessable by other PHP processes that may run on the server.
Inside The Numbers
| Label | Value |
| :---------------- | :------------------ |
| cache hits | The total number of requests that returned a cached value. |
| cache misses | The total number of requests that did not return a cached value. This number includes
L1 cache (-),
L2 non-persistent,
L2 APCu (-), and
L2 SQL misses. |
| L1 cache hits | The number of requests that were found in the L1 memory cache. |
| L1 cache (+) | Request found in the L1 memory cache with data (positive hits). |
| L1 cache (-) | Request found in the L1 memory cache with no data (negative hits). |
| L1 cache misses | The number of requests not found in the L1 memory cache. |
| L2 non-persistent | L1 cache misses in a non-persistent group (not in L2 cache). |
| L2 APCu hits | The number of L1 cache misses (minus L2 non-persistent) that were found in the L2 APCu cache. |
| L2 APCu (+) | Request found in the L2 APCu cache with data (positive hits). |
| L2 APCu (-) | Request found in the L2 APCu cache with no data (negative hits). |
| L2 APCu misses | The number of requests not found in the L2 APCu cache. |
| L2 SQL hits | The number of L2 APCu misses (or L1 cache misses) that were found in the L2 SQLite cache. |
| L2 SQL misses | The number of requests not found in the L2 SQLite cache. |
| L2 APCu updates | The number of APCu keys updated. |
| L2 APCu deletes | The number of APCu keys deleted. |
| L2 SQL selects | The number of SQLite select statements executed. |
| L2 SQL updates | The number of SQLite records updated. |
| L2 SQL deletes | The number of SQLite records deleted. |
| L2 SQL commits | The number of SQLite transactions executed to update and delete records. |
- When a request results in a L2 SQL miss, the key is added to the L1 memory or L2 APCu cache as a miss so that additional requests for the same key do not result in additional SQL selects. This is known as a negative hit and still counted as a cache miss making the cache hit ratio (93.10%) understated.
Object cache statistics may be found:
- In the WP Object Cache dashboard panel.
- Uses
$wp_object_cache->showDashboardStats()
- In the Debug Bar > Object Cache panel.
- Uses
$wp_object_cache->stats()
- In the Query Monitor > Logs > Info panel.
- Uses
$wp_object_cache->getCurrentStats()
- In a wp_admin_notice block when display_stats is set for sampling.
- Uses
$wp_object_cache->htmlStats()
{eac}ObjectCache is an extension plugin to and is fully functional with installation and registration of
{eac}Doojigger.
However, the core
object-cache.php file may be installed without {eac}Doojigger (referred to as 'detached' mode).
In detached mode, the plugin will attempt to copy the
object-cache.php file to the
/wp-content folder on activation, or you may manually copy the
object-cache.php file from the plugin
/src folder to the
/wp-content folder to activate. Options can then be set using the documented PHP constants in the
wp-config.php file.
Automatic Plugin Installation
This plugin is available from the
WordPress Plugin Repository and can be installed from the WordPress Dashboard »
Plugins »
Add New page. Search for 'EarthAsylum', click the plugin's [Install] button and, once installed, click [Activate].
See
Managing Plugins -> Automatic Plugin Installation
Upload via WordPress Dashboard
Installation of this plugin can be managed from the WordPress Dashboard »
Plugins »
Add New page. Click the [Upload Plugin] button, then select the eacobjectcache.zip file from your computer.
See
Managing Plugins -> Upload via WordPress Admin
Manual Plugin Installation
You can install the plugin manually by extracting the eacobjectcache.zip file and uploading the 'eacobjectcache' folder to the 'wp-content/plugins' folder on your WordPress server.
See
Managing Plugins -> Manual Plugin Installation
Settings
Once installed and activated, options for this extension will show in the 'Object Cache' tab of {eac}Doojigger settings.
Additional Information
{eac}ObjectCache is an extension plugin to and is fully functional with installation and registration of
{eac}Doojigger.
However, the core
object-cache.php file may be installed without {eac}Doojigger - referred to as 'detached' mode.
In detached mode, the plugin will attempt to copy the
object-cache.php file to the
/wp-content folder on activation, or you may manually copy the
object-cache.php file from the plugin
/src folder to the
/wp-content folder to activate. Options can then be set using the documented PHP constants in the
wp-config.php file.
See Also
{eac}KeyValue - An easy to use, efficient, key-value pair storage mechanism for WordPress that takes advatage of the WP Object Cache.
Version 2.1.2 – October 25, 2025
- Reinstated
write_hooks when using APCu.
Version 2.1.1 – October 17, 2025
- FIX: proper return of empty/falsy APCu value.
- Filter out unused APCu/SQL stats on dashboard widget.
Version 2.1.0 – October 14, 2025
- Added
EAC_OBJECT_CACHE_DISABLE_ALLOPTIONS constant to disable use of WP alloptions array.
- More efficient with APCu, reduces memory and storage use.
- Requires WP 6.6.0+.
- Prefetch
alloptions and notoptions when not using APCu.
- Requests for
alloptions and notoptions may be more than 70% of cache hits.
- Support keys in pre-fetch groups (group=>key) with SQL wildcard;
- Proper implementation of the
$force option in wp_cache_get().
- Fixed pre-fetch loader.
- Added dashboard widget -
showDashboardStats().
- Use full cache pathname (not just directory) to get APCu prefix id.
- Expire last sample after 1 day.
- Rework stats array/output, including htmlStats labels.
- Disabled
write_hooks when using APCu (unnecessary).
Version 2.0.0 – September 30, 2025
- Added support for APCu caching as an intermediate layer between L1 and L2 caching.
- Add
EAC_OBJECT_CACHE_USE_DB constant to disable DB use.
- Add
EAC_OBJECT_CACHE_USE_APCU constant to disable APCu use.
- Add
EAC_OBJECT_CACHE_OPTIMIZE_MEMORY constant when using APCu.
- Removed bulk import of transients on install/rebuild.
- Added single import of transient on demand.
- Use default
flush_group() for wp_cache_set_last_changed hook.
- Removed
select_all(), use select_each().
- Add
log_stats flag and check for external logging plugins.
- Verify Query Manager active before triggering actions.
- Type hint class variables.
- Updated administrator page.
- Rework stats arrays - 0=>hits, 1=>count, 2=>size (db total adds 3=>file size).
- Many other internal changes and optimizations.
Version 1.4.1 – July 12, 2025
Version 1.4.0 – June 27, 2025
- Issue: Although setting
wp_using_ext_object_cache( false ) would seem to disable use of the object cache, this setting is rarely used.
- Fix: (A) check
wp_using_ext_object_cache() on each external function call (i.e. wp_cache_get()). This has NOT been implemented as it is likely to cause many issues throughout WordPress by disabling all object caching.
- Fix: (B) selectively check
wp_using_ext_object_cache() within the object-cache code. This has been implemented to suppress L2 (database) access only, retaining access to the current L1 (memory) cache.
wp_using_ext_object_cache( false ) may temporarily disable L2 caching while allowing L1 access.
- New (internal)
select_cursor(), select_each(), and updated select_all() methods for better cursor/array management when retrieving multiple records from L2.
- New (non-standard) sub-group or group name suffix to indicate specific attributes of a group:
- Global group -
{group}:sitewide (applies to all sites in a multi-site network).
- Non-Persistent group -
{group}:nocaching (not saved in the L2 cache).
- Permanent group -
{group}:permanent (no expiration time required or set).
- Prefetch group -
{group}:prefetch (load to L1 cache on startup).
- Enforce
wp_suspend_cache_addition() on wp_cache_set() if the key doesn't already exist.
- Circumvent $wpdb->query by using $wpdb->dbh with MySQLi to retrieve individual rows when importing transients.
- Use SQL (not get_option) to get expiration when importing transients.
- Set
wp_suspend_cache_addition(true) and wp_using_ext_object_cache(true) when exporting transients to MySQL.
- Don't set
wp_installing(true) when importing transients.
- New EAC_OBJECT_CACHE_DISABLE_TRANSIENT_IMPORT / EXPORT constants.
- Fixed potential critical error on cache create caused by file permissions.
Version 1.3.4 – June 17, 2025
- Fixed bug (potential crash) introduced with persisting prefetch groups.
Version 1.3.3 – June 10, 2025
- Save (persist) added prefetch groups since pre-fetching happens before add.
- Don't check database for prefetch group keys after pre-fetching.
Version 1.3.2 – June 3, 2025
- Fix error in object-cache.php & ObjectCache.admin when FS_CHMOD_FILE/DIR is not defined.
Version 1.3.1 – April 19, 2025
- Compatible with WordPress 6.8.
- Prevent
_load_textdomain_just_in_time was called incorrectly notice from WordPress.
- All extensions - via eacDoojigger 3.1.
- Modified extension registration in constructor.
Version 1.3.0 - April 11, 2025
- Support for 'detached' mode (installed without {eac}Doojigger)...
- Installs/uninstalls
object-cache.php on activation/deactivation hooks.
- Or manually install
src/object-cache.php to the wp-content folder.
- Added option to purge/rebuild cache on a scheduled (hourly, twicedaily, daily, weekly, monthly) basis.
- Manually:
add_action( 'some_weekly_event', [ $wp_object_cache, 'rebuild_object_cache' ] );
- assuming
some_weekly_event has been scheduled with wp_schedule_event(...).
- Added
get_group(), returns all L1 & L2 keys for a group.
- Added
delete_group() deletes all L1 & L2 keys for a group.
- flush_group() is immediate, delete_group() fetches rows and caches deletes.
- Added
set_transient_doing_cron to write_hooks array.
- Forces cache write when setting
doing_cron transient.
- Removed
action_scheduler_before_process_queue action that prevented runtime cache flush.
Version 1.2.2 - April 4, 2025
- New
write_hooks sets hook names that trigger an immediate cache write.
- Default is
[ 'cron_request', 'updated_option_cron' ]
to fix wp-cron jobs not running or rescheduling correctly.
- Can be set/overridden with
EAC_OBJECT_CACHE_WRITE_HOOKS constant.
- Added action on
action_scheduler_before_process_queue hook to prevent cache flush triggered by Action Scheduler.
Version 1.2.1 - March 30, 2025
- Use
add_event_task filter to add optimize scheduled task.
- Fix probability error when set to 25.
Version 1.2.0 - March 20, 2025
- Optimize
insert... on conflict statement.
- Use
exec() instead of query() where applicable.
- Optimize stats sample select SQL.
- Rework count/size in cache stats.
- Don't wait for mu_plugins to load prefetch groups.
- Added
optimize() method with scheduled event (daily @1am).
- Purge expired records before vacuum.
- Added
incremental_vacuum on maintenance probability.
- Allow defined constants to prevent outside actors from flushing caches.
- Reworked option constants load.
- Support Query Monitor logging and timings.
- Prevent maintenance on ajax/cron/not-php requests.
- New
init() to allow instantiation before triggering use.
- New
getStatsCache(), getStatsGroups(), getStatsDB() used by getStats().
- Sampling/maintenance probability per blog/global.
display_stats is numeric indicating every n requests to sample.
- Isolated admin extension for backend only.
Version 1.1.0 - March 13, 2025
- Change SQLite
synchronous from OFF to NORMAL.
- Use
insert... on conflict rather than replace.
- Add SQLite
mmap_size to enable memory mapped I/O.
- Add SQLite
page_size to adjust page size.
- Add SQLite
cache_size to adjust cache size.
- Add
WITHOUT ROWID when creating table.
- Ensure correct blog id when building key in multisite environment.
- Optimize pre-fetch.
- Export cached transients back to MySql when disabled.
- Requires Sqlite3 version 3.24.0.
Version 1.0.4 - May 24, 2024
- Fix for updated {eac}Doojigger Advanced Mode, remove from 'Tools' tab.
Version 1.0.3 - April 3, 2024
- Added notice if eacDoojigger is not active.
- Delete sqlite file(s) rather than records on flush.
- Set wp_installing and fixed expiration when importing transients,
- switch_to_blog() now flushes L1 and reloads prefetch groups.
- flush_blog() use
$this->blog_id instead of get_current_blog_id().
- Suppress flush message when 0 records flushed.
- Use
options_form.requestSubmit() instead of options_form.submit().
Version 1.0.2 - February 17, 2024
- Minor updates as per WordPress review team.
- Changed EAC_OBJECT_CACHE to EAC_OBJECT_CACHE_VERSION.
- Added ABSPATH check in wp-cache.php.
- Escape output of calculated cache ratio.
Version 1.0.1 - January 24, 2024
- Improved sanitization and output escaping.
- Changed constant EACDOOJIGGER_OBJECT_CACHE to EAC_OBJECT_CACHE.
Version 1.0.0 - December 9, 2023
- First public release, submitted to WordPress review team.
Version 0.5
- Testing in live, multisite environment.
- Ignore 'force_cache' flag (force L2 read).
- if we've updated a key, but not written yet, then force a persistent load, we lose that value.
- Added wp_flush_blog() function.
- Cache L2 misses saving sqlite selects on records known to not exist.
- Don't attempt read or delete on non-persistent groups.
- Added cache hit ratio to stats.
- Remove function call counts (for testing).
Version 0.4
- Enhanced admin screen with advanced options.
- Group constants used:
- EAC_OBJECT_CACHE_GLOBAL_GROUPS
- EAC_OBJECT_CACHE_NON_PERSISTENT_GROUPS
- EAC_OBJECT_CACHE_PERMANENT_GROUPS
- EAC_OBJECT_CACHE_PREFETCH_GROUPS
- Added non-standard wp_cache_add_permanent_groups(), wp_cache_add_prefetch_groups()
Version 0.3
- Parameterize timeout, retries.
- Import transients from MySQL.
- Rework select/replace/delete SQL.
- New select_one(), select_all() methods.
- key_exists(), key_exists_memory(), key_exists_database() replace _exists().
- Add permanent groups (allow no expiration, overriding default expire).
- Add function call counts (for testing).
Version 0.2
- Support add/get/set/delete _multiple methods (non-standard replace_multiple).
- Add pre-fetch groups.
- Add delayed writes.
- Add settings via defined constants.
- Add more detailed counts/stats.
- Manage install/uninstall, activate/deactivate actions.
Version 0.1
- Simple memory caching with get/set persistent cache supporting wp-cache functions.
- Testing SQLite methods.