It’s  easy enough to make custom database queries in wordpress… Usually, bad queries, at least in terms of performance.

Yeah, I’m looking at you query_posts(). I’ve seen templates with 15 various calls to query_posts, creating 40 or so SQL requests for one single page. For each single pageview.

So what, then, would be the right way? Most of the time, we actually want to modify the main database query, that is, the one that is linked to the requested url. For instance, http://domain.com/category/sins would be the URL at which you want to display the list of all your sins (and there are many). So the main query at that url will, if not touched, sends back the amount of posts specified in Settings > Reading > number of posts sitting in the category with slug "sins".

Say you have specified a value of 20 posts to be displayed as a default. It’s fine for all categories (especially in category “graces”!) but you don’t want to display all your sins; you believe only 2 would suffice (nobody likes perfect people). Problem: how do you have 10 for all categories, but only 2 for the “sins” category?

Easy peasy honey, meet mister badass “pre_get_posts”.

pre_get_posts allows you to modify the main query object before the actually SQL query is made. It happens right after WordPress deduces the SQL query related to the url request, and before it launches the SQL query.

Now, as you know, great power… great responsibilities. pre_get_posts is launched at EVERY request, including those pointing to the wp-admin part, RSS feed, etc. So you need to make sure you are modifying the right request, and not all, otherwise your default post number setting will never be used.

Here is a nice pre_get_posts boilerplate I made to help you get started.

Read more about pre_get_posts here and there.