Faster MODX Listings: Why pdoResources Beats getResources for News Indexes and Menus
Slow MODX listing pages are usually a snippet problem, not a server problem. Here's why pdoResources outperforms getResources, with a working example, pagination setup, and the trade-offs to check first.
13 Dec 2025, 14:40 UTC

Your MODX news archive has grown to a few hundred articles, and the listing page now takes noticeably longer to render than the rest of the site. The culprit is usually not the database or the server — it's the snippet doing the listing. If that snippet is getResources, there's a well-established fix: swap it for pdoResources from the pdoTools package, which is designed as a faster, near drop-in replacement.
Why getResources slows down as your tree grows
getResources has been the standard listing snippet for years, and it works. The problem is how it works: it renders each row through its own chunk parse, and template variables (TVs) are typically fetched with extra queries per row. On a listing of 10 items with a couple of TVs, that's fine. On a section that queries a deep branch of the resource tree, the query count and chunk parsing overhead multiply quickly.
pdoTools takes a different approach. It builds fewer, more efficient queries — TVs can be pulled in via joins rather than per-row lookups — and its chunk processing is leaner. The result is the same HTML with measurably less work per request. The parameters are deliberately close to getResources, so migration is usually a rename plus a review of a few options.
A worked example: a news index
Assume your news articles live under resource ID 3, each with a TV called newsImage, and you want the 10 most recent by publish date. A typical pdoResources call looks like this:
[[!pdoResources?
&parents=`3`
&depth=`2`
&tpl=`newsRow`
&limit=`10`
&includeTVs=`newsImage`
&sortby=`publishedon`
&sortdir=`DESC`
]]Two things to note here. First, the call is uncached — [[!...]] rather than [[...]] — because this listing will be paginated and sorted, and you don't want MODX serving a stale cached fragment. Second, &includeTVs tells pdoTools to join the TV values into the main query instead of fetching them row by row, which is where a big part of the speedup comes from.
The newsRow chunk is ordinary MODX markup — placeholders like [[+pagetitle]], [[+publishedon]], and [[+tv.newsImage]] — so your existing getResources templates usually carry over unchanged.
Pagination with pdoPage
For anything longer than one page, the companion snippet pdoPage (same package) handles pagination without extra extras. You wrap your listing in the pdoPage call and it takes over the &limit and offset logic, rendering either classic ?page=2 links or an AJAX "load more" button, depending on configuration.
Because pdoPage reacts to request parameters, the whole call must stay uncached. That's the general rule: cache listing output only when it's identical for every visitor and every request; keep it uncached the moment pagination, filtering, or user-specific content enters the picture.
Migration gotchas worth checking
- Parameter drift. pdoResources is close to getResources but not identical. Defaults for things like sorting and which fields are selected can differ, so don't blind copy-paste a call — compare the parameters you actually rely on, then verify the output order on a test page.
- Depth still costs. A large
&depthover a big tree is slow no matter which snippet you use. Constrain queries with specific&parentsvalues and&whereconditions instead of scanning whole branches. - It's a dependency. pdoTools is a third-party extra, not MODX core. You're taking on an upgrade path, and you should confirm the installed pdoTools version supports your MODX branch before deploying. For a tiny one-off list of five links, core getResources — or a small custom snippet using xPDO directly — may be the simpler thing to maintain.
Verify the win before you commit
Don't migrate on faith. Install pdoTools from the MODX package manager on a staging copy, duplicate one real listing, and compare. MODX can log query counts and parse times, and your browser's network timing gives a quick external check; run the old and new versions side by side on the same data. Then test pagination explicitly: navigate to page 2 and confirm results don't repeat page 1 and that the cache isn't serving stale pages. Finally, after any template or TV change, clear the MODX cache so you're not benchmarking yesterday's output.
The actionable takeaway: if a MODX listing page is slow and it's powered by getResources, pdoResources plus pdoPage is the lowest-effort, highest-certainty optimization available — provided you keep the call uncached where it needs to be and verify the parameter differences before flipping the switch.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.