⚡ Don’t Let WP_Query Kill Your Database
WP_Query is powerful but dangerous. Bad queries = slow site. Learn best practices for performance.
📝 Do’s and Don’ts
// ❌ DON'T: Query inside loop
while (have_posts()) {
the_post();
$related = new WP_Query(['post_type' => 'post', 'posts_per_page' => 5]);
// Runs 10 times = 10 extra queries!
}
// ✅ DO: Query once, use caching
$related = new WP_Query(['post_type' => 'post', 'posts_per_page' => 50]);
$related_posts = $related->posts;
// ❌ DON'T: Query all posts without limit
$query = new WP_Query(['posts_per_page' => -1]); // Loads everything!
// ✅ DO: Limit results
$query = new WP_Query(['posts_per_page' => 50]);
// ❌ DON'T: No cache for expensive queries
$recent = new WP_Query($args);
// ✅ DO: Cache results with transients
$recent = get_transient('recent_posts');
if (false === $recent) {
$recent = new WP_Query($args);
set_transient('recent_posts', $recent, HOUR_IN_SECONDS);
}
🎯 Optimize Query Parameters
$args = [
'posts_per_page' => 10,
'no_found_rows' => true, // Skip pagination calc (faster)
'update_post_meta_cache' => false, // Skip meta cache (if not needed)
'update_post_term_cache' => false, // Skip term cache (if not needed)
'fields' => 'ids', // Only get IDs (much faster)
'cache_results' => true, // Cache query results
];
// Only get what you need
$ids = get_posts($args); // Returns array of IDs only
// Then get specific post data if needed
foreach ($ids as $id) {
$title = get_the_title($id);
}
✅ Use wp_reset_postdata()
- Always call wp_reset_postdata() after custom WP_Query loops
- Prevents conflicts with main query
- Use wp_reset_query() if you used query_posts() (avoid query_posts!)
“Homepage did 50+ queries. Added ‘no_found_rows’ and ‘update_post_meta_cache’ → queries dropped to 15. Page load halved. Tiny changes, huge impact.”
