Opened 4 weeks ago
Closed 13 hours ago
#66098 closed enhancement (fixed)
Add pre_wp_count_posts filter for the post counts query
| Reported by: | jdeep | Owned by: | abhishekfdd |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.2 |
| Component: | Posts, Post Types | Version: | |
| Severity: | normal | Keywords: | has-patch has-unit-tests |
| Cc: | Focuses: | performance |
Description (last modified by )
wp_count_posts() offers no way to bypass its GROUP BY post_status aggregate and serve the counts from another source.
The result of wp_count_posts() is cached in the object cache under the key returned by _count_posts_cache_key( $type ). That key is deleted on every status transition. On a large site with frequent publishing the cache is therefore almost never warm: nearly every admin request misses and re-runs the full aggregate over the entire post type, which takes several seconds on a table with 1M+ posts.
For a large publisher, an exact real-time count in the admin dashboard is not important as long as they are able to publish without the list screen taking several seconds to load. We can happily trade a little count accuracy for performance.
We can run the aggregate in the background using Action Scheduler and store the result in a durable store (an option). But to make wp_count_posts() actually return that value and skip its query, we have to fill core's object cache by hand. On every request, we wp_cache_set() the stored counts under the key returned by internal _count_posts_cache_key() function, so core's wp_count_posts() hits the cache.
With a pre_wp_count_posts filter, wp_count_posts() could serve the pre-computed value (for whoever wants to trade off accuracy for performance) and skip the main query entirely.
Change History (11)
#4
@
4 weeks ago
- Keywords needs-patch added
- Milestone Awaiting Review → 7.2
This seems to make sense to me.
@jdeep Do you want to open a PR?
#5
@
4 weeks ago
Sure @westonruter, will raise a PR for it.
I was waiting to get a second opinion on whether this is a worthwhile change.
#8
in reply to: ↑ 7
@
9 days ago
Replying to abhishekfdd:
@jdeep Happy to help if you haven't started, I have a patch ready.
Sure @abhishekfdd please go ahead!
This ticket was mentioned in PR #13846 on WordPress/wordpress-develop by @abhishekfdd.
9 days ago
#10
- Keywords has-patch has-unit-tests added; needs-patch removed
Adds a pre_wp_count_posts filter to wp_count_posts(). Returning a non-null value short-circuits the function, skipping the object cache lookup and the GROUP BY post_status query, so sites with large post tables can serve counts from a precomputed source.
- Runs after
post_type_exists()and before the cache lookup. - The short-circuited value is not cached.
- The value is still passed through
wp_count_posts, and any registered status missing from it is set to 0.
Unit tests are in tests/phpunit/tests/post/wpCountPosts.php.
See #66098.
Trac ticket: [](https://core.trac.wordpress.org/ticket/66098)
Use of AI Tools
Tool(s): Claude Code
Model(s): Opus 5.5
Used for: Drafted the patch and unit tests. I reviewed the implementation, checked the design against existing patterns such as pre_count_users, and ran the new tests and the full post test group locally."
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
This was initially proposed in #61097 for a totally different use-case (of overriding a less performant query) but the filter was later removed from the final patch as the query itself was updated.