Make WordPress Core

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 westonruter)

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)

#1 @jdeep
4 weeks ago

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.

Last edited 4 weeks ago by jdeep (previous) (diff)

#2 @jdeep
4 weeks ago

  • Description modified (diff)

#3 @westonruter
4 weeks ago

  • Description modified (diff)

#4 @westonruter
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 @jdeep
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.

#6 @westonruter
4 weeks ago

  • Owner set to jdeep
  • Status new → assigned

#7 follow-up: @abhishekfdd
9 days ago

@jdeep Happy to help if you haven't started, I have a patch ready.

#8 in reply to: ↑ 7 @jdeep
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!

#9 @jdeep
9 days ago

  • Owner changed from jdeep to abhishekfdd

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."

#11 @peterwilsoncc
13 hours ago

  • Resolution → fixed
  • Status assigned → closed

In 64245:

Posts, Post types: Introduce pre-flight filter to wp_count_posts().

Introduces the pre-flight filter pre_wp_count_posts to wp_count_posts().

Returning a non-null value short-circuits wp_count_posts(), skipping both the object cache lookup and the database query. This allows the counts to be served from another source, such as a value pre-computed in the background, when an exact real-time count is not required.

Any registered post status missing from the filtered value are added to the result and set to zero.

The returned value is not cached and passed through the wp_count_posts filter.

Developed in ​https://github.com/WordPress/wordpress-develop/pull/13846.

Props abhishekfdd, jdeep, soean, westonruter.
Fixes #66098.

Note: See TracTickets for help on using tickets.