CoCart Products Cache
WordPress plugin for fast CoCart product endpoints via static JSON caching
by ehtishamnaveed · github.com/ehtishamnaveed/cocart-products-cache
Install
The author publishes release zips, so WP-CLI can install straight from GitHub:
wp plugin install https://github.com/ehtishamnaveed/cocart-products-cache/releases/download/v4.1.1/cocart-products-cache.zipA WordPress plugin that makes CoCart's /cocart/v2/products and /cocart/v2/products/{id} endpoints respond in under 10 ms by serving all product data from a single static JSON file — zero database queries per request.
The Problem
CoCart's default products endpoint runs live WooCommerce + database queries on every request. For stores with 50–500+ products this typically costs 200–800 ms per page load and puts unnecessary load on the database.
How It Works
The plugin intercepts the CoCart REST route before it ever reaches CoCart, using WordPress's rest_pre_dispatch filter. Requests are served directly from a pre-built JSON file stored in wp-content/uploads/.
Browser → WordPress REST API
↓
rest_pre_dispatch ← plugin intercepts here
↓
Read JSON file ← ~1–5 ms (OS file cache)
↓
Return response ← CoCart-compatible format
What never runs: WooCommerce product queries, database joins, CoCart response formatting, authentication middleware.
Features
- Zero DB queries per product request after initial build
- Both endpoints cached — collection (
/products) and single (/products/{id}) - Incremental updates — only changed products are rewritten; editing one product takes ~50 ms regardless of catalog size
- Smart batching — multiple saves within 5 seconds are batched into one file operation
- Memory-safe full rebuild — chunked streaming with
fwrite(), handles 10 000+ products without hitting PHP memory limits - Category filtering in PHP —
?category=slugfilters the in-memory array, no separate files or DB queries - CoCart-native format — output is identical to CoCart's own response; no frontend changes needed
- Graceful fallback — if a product isn't cached yet, the request falls through to live CoCart
Requirements
| Requirement | Minimum |
|---|---|
| WordPress | 6.3+ |
| PHP | 7.4+ |
| WooCommerce | 8.0+ |
| CoCart | 3.x |
Installation
- Download or clone this repository
- Copy the
cocart-products-cachefolder intowp-content/plugins/ - Activate the plugin in WP Admin → Plugins
- The cache builds automatically on activation
Or install as a single file: upload just cocart-products-cache.php to wp-content/plugins/cocart-products-cache/.
Cache Management
Automatic Updates
The cache stays in sync automatically — no manual intervention needed:
| Trigger | Action |
|---|---|
| Product saved / updated | Updates only that product |
| Variation saved | Updates the parent product |
| Stock changes | Updates the affected product |
| Product trashed / unpublished | Removes it from cache |
| Product deleted | Removes it from cache |
| Scheduled sale starts / ends | Full rebuild (WooCommerce doesn't report which products changed) |
Manual Flush
Go to WP Admin → Plugins and click Flush Cache next to this plugin. This deletes the current cache file and immediately rebuilds it.
Admin Benchmark Tool
benchmark.php adds a page at WP Admin → Tools → Cache Benchmark that measures:
- Read speed at various product counts (100 / 500 / 1 000 / 2 500 / 5 000 / 10 000)
- Memory usage per request
- Write speed for full rebuild vs incremental update
- Plain-English verdict on performance at your catalog scale
Response Format
The cached response is byte-for-byte identical to CoCart's native format.
Collection — GET /wp-json/cocart/v2/products
Returns a JSON array of product objects. Response headers include:
X-WP-Total: 247
X-CoCart-Cache: HIT
X-Cache-Generated: 2025-01-15 10:30:00 UTC
Cache-Control: public, max-age=300
Single Product — GET /wp-json/cocart/v2/products/{id}
Returns a single product object.
X-CoCart-Cache: HIT
X-Cache-Generated: 2025-01-15 10:30:00 UTC
Product Object Shape
{
"id": 42,
"name": "Classic T-Shirt",
"slug": "classic-t-shirt",
"type": "simple",
"sku": "TSH-001",
"description": "<p>Full product description HTML</p>",
"short_description": "<p>Short description HTML</p>",
"featured": false,
"prices": {
"price": "2999",
"regular_price": "3999",
"sale_price": "2999",
"on_sale": true,
"currency": {
"currency_code": "USD",
"currency_symbol": "$",
"currency_minor_unit": 2
}
},
"images": [
{ "id": 101, "src": "https://example.com/wp-content/uploads/shirt.jpg", "alt": "Classic T-Shirt" }
],
"categories": [
{ "id": 5, "name": "Apparel", "slug": "apparel" }
],
"stock": {
"stock_status": "instock",
"is_in_stock": true,
"stock_quantity": null
},
"weight": "",
"dimensions": { "length": "", "width": "", "height": "" },
"variations": [],
"related": []
}
Prices are minor-unit integers as strings — e.g.
"2999"means $29.99 whencurrency_minor_unitis2. This matches CoCart's native format exactly.
Supported Query Parameters
| Parameter | Behaviour |
|---|---|
category |
Filtered in PHP from the cache — instant, no DB query |
search, sku, min_price, max_price, attribute, attribute_term |
Falls through to live CoCart (dynamic, can't be pre-cached) |
Cache File Location
wp-content/uploads/cocart-products-cache.json
The file is written atomically (to a .tmp file, then renamed) so a partial write never corrupts a live request.
Performance
Tested on a VPS with 247 products:
| Before (live CoCart) | After (cached) | |
|---|---|---|
| Response time | 280–450 ms | 3–8 ms |
| DB queries | 40–60 | 0 |
| PHP memory | ~18 MB | ~4 MB |
Pairing With the Frontend
This plugin pairs with CoCart-API-SDK
License
GPL-2.0-or-later
Releases
1 release. Each count is every asset in that release; expand a row for the breakdown.