Cache Off vs Cache On: Choosing Thymeleaf Template Reload Strategy
0 reputation · 27 Jun 2020, 16:50 UTC
0 reputation · 27 Jun 2020, 16:50 UTC
Determine the optimal configuration for spring.thymeleaf.cache that balances rapid template iteration during local development with deterministic, performant rendering in production, especially in containerized or clustered deployments.
When spring.thymeleaf.cache is set to false, Thymeleaf checks the file system’s last‑modified timestamp on every render, enabling instant visual feedback without application restarts. In production, setting the flag to true loads each template once, parses it into an internal DOM, and reuses that representation, eliminating I/O overhead. However, many deployment pipelines mount templates from read‑only volumes or symlinked directories where timestamps do not update reliably; this can cause the cached template to serve stale content even after a new build is deployed. A documented alternative is to explicitly clear the resolver cache (e.g., via a ContextRefreshedEvent listener or Spring Boot DevTools), but this adds operational complexity and a potential race window during releases.
spring.thymeleaf.cache reliably prevent stale template rendering, or should we rely on explicit cache invalidation?34775 reputation · 28 Jun 2020, 00:14 UTC
spring.thymeleaf.cache=false: It reliably prevents stale renders if the template files are updated in-place on a volume that all containers see with updated mtime. With immutable images (templates baked into the image), cache=false adds unnecessary I/O; cache=true is safe because each new pod starts with fresh templates.spring.thymeleaf.cache=true (default in production) parses each template once at startup. Changes require JVM restart or explicit TemplateEngine.clearTemplateCache().spring.thymeleaf.cache=false checks the file’s last‑modified timestamp on every render. In local development this gives instant feedback. In containers it adds a stat() syscall per request.cache=false only when a development profile is active; it does not activate in production.ContextRefreshedEvent listener or Actuator endpoint works but introduces a race condition between pod start and cache clear.| Deployment Model | Cache Setting | Invalidation Approach |
|---|---|---|
Immutable container image (templates in src/main/resources/templates) | true | None needed; new image = new templates |
| Externalized templates on shared volume (PVC, hostPath) | false | Atomic volume update (symlink swap) so mtime changes are visible instantly |
| Kubernetes ConfigMap for templates | false + rolling restart | ConfigMap updates are eventually consistent; rolling restart guarantees consistency |
curl -s http://localhost:8080/actuator/configprops | jq '.[] | select(.prefix=="spring.thymeleaf")'
# or
./mvnw spring-boot:run --spring.profiles.active=prod -Dspring.thymeleaf.cache=true
wrk -t4 -c100 -d30s http://localhost:8080/template-heavy-endpoint
# run with cache=true and cache=false, compare p99 latency and CPU
docker exec touch /templates/foo.html
# then request the page; with cache=false change appears immediately
If you are using Kubernetes ConfigMaps for templates, confirm whether your deployment strategy includes a rolling restart or an inotify‑based reloader (e.g., kubectl rollout restart or a sidecar like stakater/reloader). This determines whether cache=false alone is sufficient or if you must accept a staleness window.
StandardTemplateResolver key collision when multiple template locations share the same logical name (classpath vs file). Verify with DEBUG logging for org.thymeleaf.TemplateEngine.spring.template.provider.cache (since 2.3) interacts with spring.thymeleaf.cache; ensure only one resolver is active.cache=false under your specific load profile should be measured; the 1–5 ms estimate varies with filesystem type (local SSD vs network volume).Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.