{"id":357611,"date":"2026-09-02T09:18:16","date_gmt":"2026-09-02T09:18:16","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/yac-object-cache\/"},"modified":"2026-09-10T05:09:21","modified_gmt":"2026-09-10T05:09:21","slug":"yac-object-cache","status":"publish","type":"plugin","link":"https:\/\/lij.wordpress.org\/plugins\/yac-object-cache\/","author":23553343,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.3.0","stable_tag":"1.3.0","tested":"7.1","requires":"5.6","requires_php":"7.0","requires_plugins":null,"header_name":"Yac Object Cache","header_author":"Laruence <laruence@php.net>","header_description":"Yac (lock-free shared memory) backed object cache for WordPress. Auto-deploys the object-cache.php drop-in on activation. No external servers: the cache lives in shared memory inherited by PHP-FPM workers.","assets_banners_color":"351d56","last_updated":"2026-09-10 05:09:21","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/laruence\/wp-yac-cache","header_author_uri":"https:\/\/www.laruence.com","rating":5,"author_block_rating":0,"active_installs":0,"downloads":117,"num_ratings":1,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.2.2":{"tag":"1.2.2","author":"laruence","date":"2026-09-02 10:00:40","revision":3677677},"1.3.0":{"tag":"1.3.0","author":"laruence","date":"2026-09-10 05:09:21","revision":3689305}},"upgrade_notice":[],"ratings":{"1":0,"2":0,"3":0,"4":0,"5":1},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3677662,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3677662,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3677662,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3677662,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.2.2","1.3.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3689453,"resolution":"1","location":"assets","locale":"","width":1094,"height":450},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3689453,"resolution":"2","location":"assets","locale":"","width":1619,"height":218},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3689453,"resolution":"3","location":"assets","locale":"","width":2236,"height":642},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3689453,"resolution":"4","location":"assets","locale":"","width":2244,"height":1346}},"screenshots":{"1":"Dashboard widget: hit rate, uptime, key slots, values occupied and the 24-hour counters.","2":"Tools \u2192 Yac Object Cache: the status bar, with the live shared-memory round trip.","3":"Tools \u2192 Yac Object Cache: cache status \u2014 hit rate, hits and misses over Today \/ Yesterday \/ Last 7 days, with the capacity diagnosis on hover.","4":"Tools \u2192 Yac Object Cache: shared memory contents \u2014 keys-by-group pie, occupancy totals and the largest (or hottest) entries, each clickable for the entry inspector."}},"plugin_section":[262246],"plugin_tags":[146,7913,247,278828,278827],"plugin_category":[52,54],"plugin_contributors":[278829],"plugin_business_model":[],"class_list":["post-357611","plugin","type-plugin","status-publish","hentry","plugin_section-dashboard-widgets","plugin_tags-cache","plugin_tags-object-cache","plugin_tags-performance","plugin_tags-shared-memory","plugin_tags-yac","plugin_category-performance","plugin_category-security-and-spam-protection","plugin_contributors-laruence","plugin_committers-laruence"],"banners":{"banner":"https:\/\/ps.w.org\/yac-object-cache\/assets\/banner-772x250.png?rev=3677662","banner_2x":"https:\/\/ps.w.org\/yac-object-cache\/assets\/banner-1544x500.png?rev=3677662","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/yac-object-cache\/assets\/icon-128x128.png?rev=3677662","icon_2x":"https:\/\/ps.w.org\/yac-object-cache\/assets\/icon-256x256.png?rev=3677662","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/yac-object-cache\/assets\/screenshot-1.png?rev=3689453","caption":"Dashboard widget: hit rate, uptime, key slots, values occupied and the 24-hour counters."},{"src":"https:\/\/ps.w.org\/yac-object-cache\/assets\/screenshot-2.png?rev=3689453","caption":"Tools \u2192 Yac Object Cache: the status bar, with the live shared-memory round trip."},{"src":"https:\/\/ps.w.org\/yac-object-cache\/assets\/screenshot-3.png?rev=3689453","caption":"Tools \u2192 Yac Object Cache: cache status \u2014 hit rate, hits and misses over Today \/ Yesterday \/ Last 7 days, with the capacity diagnosis on hover."},{"src":"https:\/\/ps.w.org\/yac-object-cache\/assets\/screenshot-4.png?rev=3689453","caption":"Tools \u2192 Yac Object Cache: shared memory contents \u2014 keys-by-group pie, occupancy totals and the largest (or hottest) entries, each clickable for the entry inspector."}],"raw_content":"<!--section=description-->\n<p><a href=\"https:\/\/github.com\/laruence\/yac\">Yac<\/a> keeps the cache in shared memory inherited by every PHP-FPM worker on the machine, so a read is a hash lookup in local memory \u2014 no cache server, no socket, no network.<\/p>\n\n<p><strong>Highlights<\/strong><\/p>\n\n<ul>\n<li><strong>Fast.<\/strong> No socket, no network, no global lock \u2014 per-slot CAS, so throughput scales with workers. A 0.005 ms round trip, and ~19% faster page renders than the Memcached drop-in (141.6 vs 118.7 req\/s).<\/li>\n<li><strong>Nothing to operate.<\/strong> No cache server to install, secure, monitor or restart.<\/li>\n<li><strong>Health you can read.<\/strong> Hit rate, hits and misses charted over Today \/ Yesterday \/ Last 7 days, with a diagnosis that also says when <em>not<\/em> to add memory.<\/li>\n<li><strong>Fails soft.<\/strong> No extension, or <code>yac.enable=0<\/code>, degrades to a per-request cache and the site keeps serving.<\/li>\n<\/ul>\n\n<p><strong>Best fit<\/strong><\/p>\n\n<p>Single-node or few-node installs where all PHP workers share a machine. For multi-server clusters needing cross-node consistency, a network cache (Memcached\/Redis) suits better.<\/p>\n\n<!--section=installation-->\n<ol>\n<li><p>Install the Yac extension, any of three ways (then enable <code>extension=yac.so<\/code> in php.ini):<\/p>\n\nPECL\n\n<p>pecl install yac<\/p>\n\nPIE (the PHP Foundation's PECL successor; yac is on Packagist)\n\n<p>pie install laruence\/yac<\/p><\/li>\n<\/ol>\n\n<p>Or from source: download the latest <a href=\"https:\/\/github.com\/laruence\/yac\/releases\">release<\/a>, unzip it, then inside:<\/p>\n\n<pre><code>phpize &amp;&amp; .\/configure &amp;&amp; make &amp;&amp; make install\n<\/code><\/pre>\n\n<ol>\n<li>Install and activate Yac Object Cache. Activation deploys <code>wp-content\/object-cache.php<\/code>.<\/li>\n<\/ol>\n\n<p>That is it \u2014 no wp-config edit needed. Visit <strong>Tools \u2192 Yac Object Cache<\/strong> to verify status.<\/p>\n\n<p><strong>Optional php.ini tuning<\/strong><\/p>\n\n<pre><code>yac.enable = 1\nyac.keys_memory_size = 16M      ; ~128K slots (~32K per 4M)\nyac.values_memory_size = 64M    ; raise for large sites (big alloptions)\n<\/code><\/pre>\n\n<p><strong>Optional wp-config switches<\/strong><\/p>\n\n<pre><code>define( 'YAC_OCACHE_KEY_PREFIX', 'ab' ); \/\/ default wp; give each install its own when sites share one PHP pool\ndefine( 'YAC_OCACHE_EMPTY_TTL', 0 );     \/\/ default 21600s: lifetime cap on empty negative results; 0 disables\ndefine( 'YAC_OCACHE_DISABLE', true );    \/\/ escape hatch: force runtime-only mode\n<\/code><\/pre>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20memcached%20or%20redis%20server%3F\"><h3>Do I need a Memcached or Redis server?<\/h3><\/dt>\n<dd><p>No. That is the point \u2014 the cache lives in shared memory on the machine.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20the%20yac%20extension%20is%20not%20installed%3F\"><h3>What happens if the Yac extension is not installed?<\/h3><\/dt>\n<dd><p>The drop-in degrades to a per-request cache: the site keeps working, you lose cross-request persistence, and the status page flags the missing extension.<\/p><\/dd>\n<dt id=\"how%20are%20keys%20stored%2C%20given%20yac%27s%2048-byte%20key%20limit%3F\"><h3>How are keys stored, given Yac's 48-byte key limit?<\/h3><\/dt>\n<dd><p>As <code>&lt;YAC_OCACHE_KEY_PREFIX&gt;:&lt;group&gt;:&lt;key&gt;<\/code> (default prefix <code>wp<\/code>), verbatim while they fit the 48-byte budget; over-long keys keep the group verbatim and hash (crc32b) only the key part.<\/p><\/dd>\n<dt id=\"does%20flush%28%29%20clear%20other%20yac%20users%20on%20the%20same%20machine%3F\"><h3>Does flush() clear other Yac users on the same machine?<\/h3><\/dt>\n<dd><p>Yes. <code>wp_cache_flush()<\/code> calls <code>Yac::flush()<\/code>, which wipes the entire shared memory on the machine, including data written by other Yac users sharing the PHP pool. The admin page asks for confirmation first.<\/p><\/dd>\n<dt id=\"multisite%3F\"><h3>Multisite?<\/h3><\/dt>\n<dd><p>Yes, with a caveat: keys carry no per-blog prefix, so blogs of one install share the namespace and <code>switch_to_blog()<\/code> does not re-namespace. Give each install its own <code>YAC_OCACHE_KEY_PREFIX<\/code> when sites sharing a PHP pool must not see each other's entries.<\/p><\/dd>\n<dt id=\"what%20about%20wp_cache_flush_group%28%29%3F\"><h3>What about wp_cache_flush_group()?<\/h3><\/dt>\n<dd><p>Yac cannot delete entries by prefix, so a group flush clears the request-level copy of that group; shared entries then expire via TTL. The plugin reports <code>flush_group<\/code> as unsupported so core does not rely on it.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>No wp-config edit is needed any more: <code>WP_CACHE<\/code> is no longer required or reported. WordPress loads <code>object-cache.php<\/code> regardless of it \u2014 that constant only gates <code>advanced-cache.php<\/code> (page caching), which this plugin does not provide. The live CI run now boots WordPress without it to prove the point.<\/li>\n<li>The Cache health panel became a client-side trend chart: hit rate, hits and misses over Today \/ Yesterday \/ Last 7 days, with the window's counters and the capacity diagnosis on hover. Counters are sampled every 15 minutes into a ~7-day ring.<\/li>\n<li>Fixed the entry inspector exhausting the PHP memory limit on a busy cache: it now pages through <code>Yac::dump()<\/code> instead of accumulating the whole dump.<\/li>\n<li>Fixed the dashboard widget reporting \"0 bytes\" for values occupied. The Active bar now also shows shared-memory uptime.<\/li>\n<li>Suggested tuning raised to <code>yac.keys_memory_size = 16M<\/code> (~128K slots); 4M gives only ~32K.<\/li>\n<\/ul>\n\n<h4>1.2.2<\/h4>\n\n<ul>\n<li>Fixed stale shared-memory writes: <code>wp_cache_set()<\/code> on a key already written by <code>wp_cache_add()<\/code> in the same request skipped the shared write, so other requests kept reading the value the add stored (the <code>update_option()<\/code> pattern left the old option behind).<\/li>\n<li>Replaced <code>YAC_OCACHE_SKIP_EMPTY<\/code> with <code>YAC_OCACHE_EMPTY_TTL<\/code> (default 21600s): empty results now share as usual but expire instead of occupying a slot forever.<\/li>\n<li>The health panel's \"keys used\" reports live entries rather than the <code>slots_used<\/code> high-water mark.<\/li>\n<\/ul>\n\n<h4>1.2.1<\/h4>\n\n<ul>\n<li>Moved the PHPCS EscapeOutput annotations so WordPress.org Plugin Check recognizes the exemption; annotated <code>pre_wp_cache_get<\/code> as a core hook.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Fixed the health-ring donut disappearing: <code>wp_kses_post()<\/code> strips SVG elements.<\/li>\n<li>Renamed every plugin-owned symbol to the <code>yac_ocache_<\/code>\/<code>YAC_OCACHE_<\/code>\/<code>yac-ocache-<\/code> prefixes for WordPress.org policy (<code>wp_<\/code> is reserved for core). The <code>wp_cache_*<\/code> functions and <code>$wp_object_cache<\/code> keep their standard names; WP-CLI stays <code>wp yac status<\/code> \/ <code>wp yac flush<\/code>.<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>A stored <code>false<\/code> is now written as <code>0<\/code>: Yac's <code>get()<\/code> returns <code>false<\/code> for both a miss and a stored <code>false<\/code>, so a stored false never survived past the request.<\/li>\n<li>Top entries grew a Hottest tab (by access count) alongside Largest; the entry inspector gained Hits, Embedded-in-slot and <code>c_len<\/code>.<\/li>\n<li>Entry listings page through <code>Yac::dump()<\/code> instead of one <code>dump(-1)<\/code>, which could exhaust the memory limit.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Dashboard rebuilt around a cache-health verdict, keys-by-group pie, largest entries, configuration reference and diagnostics.<\/li>\n<li>Key format rework: <code>&lt;prefix&gt;:&lt;group&gt;:&lt;key&gt;<\/code> with no per-blog prefix; over-long keys hash only the key part.<\/li>\n<li><code>YAC_OCACHE_DISABLE<\/code> escape hatch forces runtime-only mode.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release. Yac-backed object cache with self-deploying drop-in, verbatim keys with hashed fallback, multisite support, graceful runtime-only fallback, and the admin dashboard.<\/li>\n<\/ul>","raw_excerpt":"Yac (lock-free shared memory) backed object cache for WordPress. Zero external servers, zero network round trips.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/357611","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=357611"}],"author":[{"embeddable":true,"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/laruence"}],"wp:attachment":[{"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=357611"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=357611"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=357611"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=357611"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=357611"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/lij.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=357611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}