I know the main query is fast, since it gets data after parsing the URL and after WP_Query has been instantiated. We are in OO PHP.

But is query_posts really slower than some secondary query that happens in a template for instance with get_posts, or native that you call with

// WP_Query arguments
$args = array (

// The Query
$query = new WP_Query( $args );
  • 1
    query_posts users WP_Query so it is a secondary query. If you need to use query_posts then use the pre_get_posts hook instead which is much faster than a new database call. See the most famous answer in WPSE history!
    – Howdy_McGee
    May 19, 2016 at 20:46
  • @Howdy_McGee: I know, all guys use WP_Query, this is the big boss. I just wanted to show there may not be a "big red button" bellow query_posts where it reads "Don't press here".
    – prosti
    May 19, 2016 at 20:51
  • 1
    "We are in OO PHP" lol wut? How does that mean "fast"? May 20, 2016 at 9:30
  • @Howdy_McGee the main query also uses WP_Query, so is it also a secondary query ;-) May 20, 2016 at 10:59
  • The "Don't use query_posts()" mantra isn't (just) because it's slow; it's because it overwrites the main query and can cause unexpected results. See this answer for more details.
    – Pat J
    May 25, 2016 at 2:20

2 Answers 2


You ask:

is query_posts really slower than some secondary query...

The fact is that if you're calling query_posts() from a theme then it already is a secondary query. WordPress has already queried the database once to get a certain page then it hits your query_posts() function and queries the database again creating a second query and overwriting the original request / data.

From a speed perspective you're not going to notice any difference. The query_posts() functions uses WP_Query() and takes microseconds to overwrite some global variables. The biggest overhead will come from you having to normalize your data and make up for any niche issues with pagination.

Simply put, it's all around inefficient. So, while there may not be a "big red button" that says "Don't press here!" it's pretty much implied that it shouldn't be pressed. It's not big and red but The Codex specifically states:

Note: This function isn't meant to be used by plugins or themes.

If you want to be efficient and need to override the main query - use pre_get_posts which will modify the query parameters before it calls it from the database which saves an entire database call ( in that we don't need a secondary query ).

  • I just read this codex, and there is one bug where it reads : "Note: The pre_get_posts action doesn't work for Page requests." This is actually not correct, and pre_get_posts can work with any posts, pages posts, or custom post types. It cannot work with with single pages.
    – prosti
    May 19, 2016 at 21:19
  • Also, query_posts() can "outright fail in some circumstances, (especially often when dealing with posts pagination)" (from the famous WPSE post)
    – Tim Malone
    May 19, 2016 at 21:21
  • Don't get me wrong, I like your answer, you are saying we will not note big difference. +1
    – prosti
    May 19, 2016 at 21:25
  • 1
    @prosti As far as I know pre_get_posts does work with single pages and almost any WordPress request. I've removed that portion from The Codex as I can see it's confusing ( and may be an old documentation ). For some reason I still feel the need to discourage you from using query_posts() though in favor of pre_get_posts as that filter is ultimately faster...
    – Howdy_McGee
    May 19, 2016 at 21:39

In general,

  • the query performed on the homepage,

  • query_posts( 'posts_per_page=get_option( 'posts_per_page' ) and

  • $q = new WP_Query( 'posts_per_page=get_option( 'posts_per_page' )

should have the same exact performance with very very little to no difference between them as all of the above are exactly the same by default (that is, have the same query arguments by default). This is because all of these queries uses the WP_Query class to run build and run db queries to return the queried posts. get_posts() is a bit faster although it also uses WP_Query. The big difference is that get_posts passes no_found_rows=true to WP_Query which legally breaks pagination.

What is true, the main query (primary query) runs on each and every page load according to the exact page being loaded. Removing the main loop and replacing it with a secondary query (either query_posts(), WP_Query or get_posts()) is what is referred to as making the page slow. This is because you are doing the same work twice. As I said, the main query runs regardless, so you have already queried the db for posts, and replacing the main loop with a secondary query queries the db again.

Apart from issues created with pagination and other crappy issues, this is why one should never replace the main loop from the main query with a secondary one. I have done an extensive post on this which you can read here. To alter the main query, always use pre_get_posts as it alters the query vars before the WP_Query class builds and runs the SQL query. There are also other filters (post clause filters) available in WP_Query which you can use to directly alter the SQL query

What makes query_posts bad is that it alters the main query object on which many functions rely as query_posts does the following

$wp_query = new WP_Query()

and it also alters the conditional tags. For a full explanation, you can read my answer here. A normal WP_Query does not do that

  • *should have the same exact performance with very very little to no difference between them as all of the above are exactly the same by default this is actually what I thought about the performance, but needed someone experienced to confirm me that. WE can also add in your answer "for the same query arguments".
    – prosti
    May 20, 2016 at 7:01
  • True, I have added that as part of my answer. ;-) May 20, 2016 at 7:14
  • Just a note, you can always file an edit and add constructive info to any post as you see fit. I will always accept such edits. Best part is, you can 2 rep points which helps you later on ;-) May 20, 2016 at 7:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.