Skip to content

Fix performance issues by filtering wp_unique_post_slug

The core WordPress function wp_unique_post_slug generates a unique slug for a newly published post. The function makes it possible to avoid slug conflicts (e.g., if an identical post title gets reused) by appending an integer to the end of the newer slug (e.g., monthly-report-2 or photo-17).

This behavior can become problematic when used with post types that are given default or similar slugs, such as attachments, because the function iterates through the database to find the next ID (e.g., photo-2867).

If a function making continuous SELECTs is observed in a slow New Relic trace, the wp_unique_post_slug might need a custom filter.

This issue can be observed in a slow New Relic trace where a continual series of SELECT queries are made on the post table.
For example: SELECT post_name FROM wp_posts WHERE post_name = 'monthly-report-1' with the number incrementing – and when there are 2867 matching entries in the table, this can seriously slow things down. This function is called during the post creation process but might also be called in the REST API under certain circumstances. It’s one explanation for slowness reported by editors at publishing time.

To prevent this behavior, a custom function can be applied to assign a unique ID and avoid any database lookups using the pre_wp_unique_post_slug filter added in WP 5.3. This filter can be set to only modify slug behavior for specific post types. If a site’s editors frequently upload photos with generic titles such as “uploaded photo”, it could be useful to assign unique IDs for the attachment post type. This could also be useful for custom post types generated by logging errors, or

In the following code example, the filter is modifying the slug behavior only for the post type wp_log, generated by a plugin that logs errors:

// generate a random, but not pretty, slug for a post type
add_filter( 'pre_wp_unique_post_slug', 'vip_set_log_slug', 10, 6 );

function vip_set_log_slug( $override, $slug, $post_ID, $post_status, $post_type, $post_parent ) {
    if ( 'wp_log' === $post_type ) {
        if ( $post_ID ) {
            return $post_ID;
        return uniqid( $post_type . '-' );
    return $override;

Last updated: December 22, 2023

Relevant to

  • WordPress