Using MODX Snippet Caching with &cache to Boost Performance
Learn how to enable snippet caching in MODX with the &cache property, set custom TTL, avoid stale data, and verify the cache works.
28 May 2026, 00:41 UTC

Enable caching for a snippet
The quickest way to make a snippet’s output reusable is to add the &cache=`1` property when you call the snippet. This tells MODX to store the rendered output after the first execution and serve that stored copy on later requests, skipping the PHP code entirely.
[!MySnippet? &cache=`1` ¶m=`value`]
If you ever need to turn caching off for a particular call, set &cache=`0`.
How MODX stores cached output
When a snippet is cached, MODX writes a file under core/cache/resource/ (or core/cache/context/ depending on your setup). The filename is a hash that incorporates:
- the snippet name
- all properties passed in the call (including
&cacheExpiresif set) - the current context (e.g.,
web) - the current user’s permissions when relevant
Subsequent requests that match the same hash read the file directly, so the snippet’s PHP is not executed again.
Controlling cache lifetime
By default, cached snippet output lives for the number of seconds defined in the system setting cache_expires. You can override this per call with &cacheExpires=``. For example, to cache a snippet for ten minutes:
[!MySnippet? &cache=`1` &cacheExpires=`600`]
After the TTL expires, the next request triggers a fresh execution and rewrites the cache file.
Handling dynamic data
If a snippet’s output depends on values that change per request—such as the current user ID, URL parameters, or session data—you must make those values part of the cache key. Otherwise the first rendered version will be served to all users, causing stale data.
Pass the dynamic value as a property, using an uncached placeholder to retrieve it each time:
[!MySnippet? &cache=`1` &userId=`[[!+modx.user.id]]` ¶m=`[[*id]]`]
Here [[!+modx.user.id]] is uncached, so it is resolved fresh on every request, while the snippet body itself remains cached per distinct userId value.
Common pitfalls and limits
- Side‑effects: Do not cache snippets that write to the database, send emails, or modify files. Those actions happen only on the first execution; later cached calls skip them, leading to missed operations.
- Placeholders inside cached output: If the snippet’s output contains placeholders like
[[++site_name]]or[[*pagetitle]], they are replaced once when the cache is created. Wrap the snippet in an uncached call ([! ... !]) if you need those placeholders to refresh each request. - Cache size: Large snippet outputs can fill
core/cache/quickly. Monitor the directory size and consider shortening TTL or disabling caching for very large snippets. - Namespace collisions: Two different snippets with identical name and property sets will share the same cache file. Ensure property sets differ (e.g., add a dummy property) if you need separate caches.
Verifying the cache works
You can confirm caching behavior without relying on logs:
- Create a test snippet that returns the current timestamp:
return strftime('%Y-%m-%d %H:%M:%S'); - Call it with a short TTL:
[!TestSnippet? &cache=`1` &cacheExpires=`10`] - Reload the page twice within ten seconds; the timestamp should stay identical.
- Wait more than ten seconds and reload; a new timestamp indicates the cache expired and the snippet re‑ran.
Optionally, inspect core/cache/resource/ for a file whose name matches the snippet’s cache ID and verify its content equals the timestamp string.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.