This content originally appeared on DEV Community and was authored by GP Web Dev
Core WordPress functions and classes are generally excellent regarding to performance and security.
When it comes to retrieving data from the database, the WP_Query
class and its methods provide us with a safe and efficient way to do it, avoiding complex SQL queries. There are some additional wrappers of WP_Query
, like query_posts()
and get_posts()
.
query_posts
WordPress Codex explicitly says “Its overly-simplistic approach to modifying the main query can be problematic and should be avoided wherever possible“.
This query wrapper is inefficient (re-runs SQL queries) and will fail in some circumstances, especially when dealing with posts pagination. It instantiates a new WP_Query object and reassigns that to the global wp_query
, breaking the main query that many plugins, themes and custom scripts rely on. For secondary queries (custom loops) instantiate your own WP_Query.
Use new WP_Query
or get_posts()
which are pretty much interchangeable (latter is thin wrapper for former). If you do want to alter the main query, then use the pre_get_posts
hook with $query->is_main_query()
check. pre_get_posts
is a filter for altering any query and it is most often used to alter the ‘main query’. This is the trac about the deprecation of query_posts
.
Therefore:
You should never use
query_posts()
.
get_posts
This is essentially a wrapper for a separate instance of a WP_Query
object. This isn’t a ‘Loop’, it simply returns an array of post objects.
It accepts the same arguments as WP_Query, doesn’t modify global variables and is safe to use anywhere. It passes 'no_found_rows' => true
by default so it is used for non paginated queries only. It ignores sticky posts, needs just a foreach loop to display the $post property and requires a setup_postdata( $post )
to make the template tags available. WP_Query
uses the loop and template tags are available by default.
Use
get_posts()
for some quick, non-paginated, data fetch.
WP_Query
WP_Query
is the class behind both the above functions. The power of WP_Query
derives from the possibility to create and work with your own instance of it. It is more of a general purpose tool, similar to directly writing MySQL, for a detailed custom query script.
A bit more complex with fewer restrictions, thus making it more powerful while being safe to use anywhere.
Use a
new WP_Query
for an in-depth, flexible query script.
Reset/Cleanup
- Use
wp_reset_query()
if you’ve usedquery_posts()
or altered global$wp_query
directly – hopefully you will never need to. - Use
wp_reset_postdata()
if you’ve usedthe_post()
orsetup_postdata()
to restore initial state of global $post.
Performance
All queries are eventually wrappers of WP_Query
, and while some are better than other (never use query_posts
), the performance differences of get_posts
vs WP_Query
are negligible. The WP_Query
is faster than get_posts
by a very small margin.
However parameters provided by the WP_Query
class can specifically optimize SQL queries, reducing execution time and resource consumption. (Ref. 1 | 2)
- When we don’t need pagination, we should set
no_found_rows
totrue
, making the query run dramatically faster. - When specific fields are not required, limit the returned fields to IDs:
'fields' => 'ids'
This content originally appeared on DEV Community and was authored by GP Web Dev

GP Web Dev | Sciencx (2025-02-27T23:25:16+00:00) WP Query Functions – What to use and when. Retrieved from https://www.scien.cx/2025/02/27/wp-query-functions-what-to-use-and-when/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.