WooCommerce performance Case study
A2 Fast Archive Filters
This MU plugin replaced slow archive filtering on the Javaherian Gallery store with a category-aware AJAX modal. Shoppers narrow the watch and jewelry catalog by brand, attribute and price without a full page reload.
The business problem
Filtering the catalog was one of the slowest things a shopper could do on the site. Each filter change fired heavy taxonomy and price queries on top of an already expensive archive render. p95 for the archive path sat near 5.2 seconds. I needed faster filtering that kept category pages server-rendered and crawlable.
What I delivered
- A modal filter UI driven by AJAX, with dependent options that reflect what actually exists in the current category context.
- Price buckets computed from real catalog prices with quantile logic (a2_ff_build_price_quantile_rows), so ranges follow the data instead of fixed steps.
- A transient cache layer with a 10-minute TTL, a 6-hour stale window and a 512KB value cap enforced by a2_ff_safe_set_transient.
- Automatic invalidation. save_post_product, set_object_terms and the term hooks bump a cache version behind a short lock (a2ff_cache_bump_lock).
- A safe mode (A2_FF_SAFE_MODE) with a server-rendered fallback so a JavaScript failure never blocks browsing.
Technical approach
- Price constraints run through a posts_clauses filter (a2_ff_price_posts_clauses) instead of stacked meta_query conditions.
- Matching-ID sets are capped by A2_FF_MAX_MATCHING_IDS at 20,000 so a huge category cannot blow past memory or cache-size limits.
- Every AJAX endpoint verifies the a2_fast_filter_nonce action before touching the database.
Result and evidence
Measured on production traffic, p95 for the archive path dropped from about 5.2s to about 1.7s after rollout.
Commercial value
Watch buyers compare many models before deciding. When narrowing by brand or price feels instant they stay in the catalog longer, and the server does far less repeated query work per session.
Delivery notes
I own this module end to end, from the tuning constants down to the invalidation hooks. Nobody has to remember to purge a cache by hand.
- Behaviour tunes through defined constants such as A2_FF_CACHE_TTL.
- Safe mode keeps the server-rendered path authoritative.
- Version 1.6.2 is the build running on the live store.
Readable implementation brief
implementation_brief {
project: "A2 Fast Archive Filters"
context: "WooCommerce performance"
problem: "Archive filtering was one of the most expensive buyer-facing
paths; discovery had to get faster without giving up
server-rendered category pages."
delivered: "Modal dependent filters over AJAX with safe fallback
rendering; smart price buckets and cache versioning
for a heavy catalogue."
evidence: "Archive p95 went from about 5.2s to about 1.7s on the
measured production path."
value: "Browsing got faster and the server did less repeated work,
without turning category pages into a client-only
experience."
}What this project shows
Product browsing got faster and the server did far less repeated work, without turning category pages into a risky client-only experience.
It also shows how I approach production work: isolate the constraint, choose the smallest maintainable system, and prove the result without adding avoidable operational risk.