MODX Revolution Snippet Caching with modCacheManager: Minimal Architecture Note
A concise architecture note on using modCacheManager for MODX Revolution snippet caching, covering minimal design, trust boundaries, operational checks, failure modes, and when to change the design.
05 Sept 2026, 05:48 UTC

Snippet output that is expensive to render but stable between edits is the only case where MODX Revolution snippet caching is safe. Caching the wrong output creates cross-user data leakage and stale pages that survive content edits. The decision point is whether the rendered HTML is deterministic for a given request context and safe to serve to any visitor.
Requirements
modCacheManager caches rendered snippet output, not raw PHP. A snippet is cached when called as [[SnippetName]] and uncached when called as [[!SnippetName]].
Caching is useful when:
- Output is deterministic for a given resource and context.
- Render cost is high relative to cache lookup.
- Staleness window is acceptable and can be bounded by cache_lifetime.
Caching is unsafe when output contains personal data, CSRF tokens, cart contents, or session-specific markup. Cache stores rendered HTML that may be served to multiple visitors.
Smallest suitable design
The minimal design uses the default file cache handler and a deterministic cache_key.
Snippet call example:
[[MySnippet? &cache_key=`[[*id]]-[[ *context_key]]` &cache_lifetime=`3600`]]cache_key must vary with any input that changes output. A common minimal key includes resource ID and context. cache_lifetime is in seconds. Without an explicit key MODX builds one from snippet name and properties.
Within the snippet, properties can be set programmatically:
$modx->setPlaceholder('cache_key', $modx->resource->get('id').'-'.$modx->context->get('key'));Rendered output is stored under core/cache or in the modx_cache table depending on cache handler configuration. The Manager Clear Cache action purges standard MODX cache groups; resource save clears cache for that resource.
Default file handler is sufficient for single-node sites with moderate traffic. No additional services are required.
Trust and data boundaries
Cache is a shared store. Treat it as untrusted output for the visitor.
- Never cache raw user input or session identifiers in snippet output.
- Do not cache forms with CSRF tokens unless the token is generated after cache retrieval.
- If personalization is required, vary cache_key by authenticated user identifier and ensure the cache store is access-controlled.
Custom database changes do not automatically clear MODX cache. Use a plugin on OnDocFormSave or call cache refresh methods explicitly when external data changes.
Operational checks
Disk growth. File cache lives under core/cache. Run as the web server user:
du -sh core/cacheRisk: unbounded growth if cache_lifetime is large and cache is never cleared. Include core/cache in disk monitoring and log rotation.
Cache invalidation verification. Save a resource in Manager and inspect core/cache or modx_cache to confirm entries are created and cleared for the affected resource. Edit a snippet call from cached to uncached on a resource, save, reload the frontend, and confirm dynamic content updates without manual cache clear.
Key isolation verification. Set cache_key to include *id and test two resources with the same snippet to verify each resource receives its own cached output.
Uncached execution check. Confirm [[!SnippetName]] executes on every request by observing side effects such as a timestamp or query counter that changes per load.
Failure modes
Stale content after updates if cache is not cleared. Standard resource edits clear resource cache, but snippet property changes or external data changes do not.
Cache stampede when many requests hit an expired key simultaneously. File handler serializes writes but can cause temporary spikes.
Cache_key collisions serving wrong content. Non-deterministic keys or missing context cause cross-resource leakage.
Corrupted cache files causing blank frontend or manager pages. File permission errors or partial writes can leave unreadable cache files.
Conditions that change the design
High traffic or multi-node deployment. Switch to memcached or redis cache handler to share cache across nodes and reduce disk I/O.
Personalized or e-commerce snippets. Disable caching for those snippets and use [[!SnippetName]] or vary cache_key per user with strict access control.
Multi-context installations. Add context-aware cache keys and verify context isolation in cache store paths.
Limitations. File-based cache is not shared across nodes. Cache invalidation is coarse; fine-grained invalidation requires custom plugins. Always verify behavior after changes to cache handler or snippet properties.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.