I feel there is a red button saying "Do not press" below query_posts(). For some time I am trying to demystify this phenomena with very low success to be honest.

For example, probable the main reason not to use this function is a broken pagination. Second, was it may be slow (read: calling twice), or there are better ways (pre_get_posts). There may be more reasons.

For those who may downwote this question from instinct, I would appeal, to hold at least for a week or so. There is always a second chance to do that. I am hardly waiting to see at least some answers, before a team pressure.

For those not read this post, I would say that this function is nor deprecated, nor it is marked as _doing_it_wrong, nor there are plans. Even the ticket to make it deprecated has been closed recently.

Some may say they read this function must not be used within the WordPress. I am providing in here the full function.

File: /wp-includes/query.php
79: /**
80:  * Set up The Loop with query parameters.
81:  *
82:  * This will override the current WordPress Loop and shouldn't be used more than
83:  * once. This must not be used within the WordPress Loop.
84:  *
85:  * @since 1.5.0
86:  *
87:  * @global WP_Query $wp_query Global WP_Query instance.
88:  *
89:  * @param string $query
90:  * @return array List of posts
91:  */
92: function query_posts($query) {
93:     $GLOBALS['wp_query'] = new WP_Query();
94:     return $GLOBALS['wp_query']->query($query);
95: }

You can see This must not be used within the WordPress Loop., meaning not within the WordPress loop, implying that before the WordPress loop may be not prohibited.

I noted from this post that this function is not slower than any secondary query (having the same arguments).

Bottomline, speaking of the pagination query_posts is much better solution for the pagination than the get_posts since get_posts actually disables SQL_CALC_FOUND_ROWS.

Some good thoughts on the query_posts may be:

  • the query arguments are not limited, you can set anything you like.
  • you can even set the arguments to use pagination, if you don't plan to use core pagination functions; super easy you can create your own pagination
  • in a typical blog only small portion of the pages, may use pagination. The most of the pages, in a majority of regular simple cases, don't even use pagination so to do something quick and to reuse the main query templates (read loop) query_posts may be handy.

These are just a the few thoughts, I am sure there are more, but certainly If you know what you are downing you cannot be wrong.

Do no

  • after you are done with query_posts() results you should be using wp_reset_query() this restores the main query.
    – stoi2m1
    Commented May 20, 2016 at 22:50

3 Answers 3


query_posts() is useful in cases when there is no main query: calls to wp-admin/admin-ajax.php, wp-admin/admin-post.php or wp-login.php for example.

Yes, you can achieve the same results there without query_posts() and slightly less compact code instead. But if you don't have to care about side effects, using query_posts() is acceptable.


Whenever the main query is available, which is for every front end page load regardless of which page/archive is loaded, you should use pre_get_posts to alter the main query's query vars before the SQL query is build and executed. This goes for each and every page where you need to alter the main query. This is the RECOMMENDED way to alter the main query. Doing it this way will not result in any extra db queries being made, period. For true pages and static front pages, you can always use my PreGetPostsForPages class or even the pre_get_posts method described by @birgire here.

You should never ever replace the main query with a custom one, neither using query_posts, a new instance of WP_Query or get_posts. This adds extra db calls per page load because the main query runs regardless. If you replace the main query with a custom one, you are running twice as many db calls which also increases page load times. Not just that, pagination becomes a nightmare. You should take your time and read this answer I have done on pagination.

You should only ever run custom queries for things like sliders, widgets, related posts and navigation menus, never ever to replace or alter the main query.

query_posts still stays a very problematic way to run custom queries as it alter the main query object stored in $wp_query ($GLOBALS['wp_query']) because so many functions and plugins relies on the main query object to run things like pagination and related posts and breadcrumbs

As @toscho already mentioned, only use query_posts when there is no main query, which is for ajax calls, and some pages on the admin side. Apart from that, you really really should avoid using it, accepts when you really need to break something on the front end.

As I said, there is absolutely no need at all to run any type of custom query in place of the main query just to alter or modify the output from the page. If you really need better performance and faster loading times, use pre_get_posts to alter the main query and never replace it for whatever reason at all. Custom queries are meant to do additional stuff like widgets, related posts and sliders


As final note, and proof, download and install the Query Monitor plugin. This way you can see the drastic increase in page load time and db calls when you replace the main query with any custom query and how there is no difference when using pre_get_posts


Opposite from the common believes query_posts is harmless if you know how to use it. I tried here to provide more arguments.

In here I will add a simple outline that you never should rely on: $GLOBALS['wp_query'].

You should rely on $GLOBALS['wp_the_query'] that should be frozen. If you like to reset the $GLOBALS['wp_query'] just use wp_reset_query.

Use case

enter image description here

For example, if you need this on a homepage, after the main loop, you may call query_posts for the cpt1 and later query_posts again for the cpt2.

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.