Why recompiling CFML templates after an upgrade matters
Upgrading Adobe ColdFusion (2016/2018/2021/2023) typically brings a new Java runtime, an updated compiler, and changes in language semantics or Security policies. CFML templates (.cfm, .cfc, .cfm tags) are compiled to Java bytecode and cached on disk and in memory. After an upgrade, those cached classes can be stale or incompatible, causing sluggish first requests, inconsistent behavior, or—worst—runtime errors. Proactively recompiling templates ensures predictable Performance and compatibility, reduces cold starts, and helps you catch issues before traffic hits the upgraded environment.
Prerequisites / Before You Start
- Verify target versions:
- Adobe ColdFusion edition and version (e.g., 2021 Update 12, 2023 Update 7).
- Supported Java version (e.g., Temurin/OpenJDK 11/17 depending on your CF version).
- Web server connector version (IIS/Apache wsconfig).
- CF Packages (cfpm) installed if your app relies on modules (e.g., PDFg, ZIP, Image).
- Backups and rollbacks:
- Full filesystem backup for application code and CF Configuration (cfusion/instance directories).
- Database snapshot/backup and ORM caches if using Hibernate (ColdFusion ORM).
- Export Administrator settings (CAR or manual export) and keep web server configs.
- Access and permissions:
- OS account with permissions to stop/start ColdFusion services.
- Read/write access to the CFML application directories and the cfclasses folder.
- Administrator credentials for ColdFusion Administrator and web server.
- Disk space and memory:
- Sufficient free disk space for compiled classes in cfclasses.
- Adequate heap memory for warm-up compilation spikes.
- Environment alignment:
- Staging or pre-production environment mirrors production (same code, mappings, JVM args).
- All CF mappings validated (Administrator > Mappings, and any per-Application mappings).
- Maintenance window:
- Communicate downtime (if any) or deploy a blue/green or rolling approach.
- Tooling:
- Command-line access to cfcompile or administrative UIs.
- cURL, JMeter, or similar for warm-up scripts.
Understanding how ColdFusion compiles templates
CFML compilation basics
- CFML templates are compiled to Java bytecode (class files).
- Compilation results are stored both in memory and on disk in a “cfclasses” directory.
- At runtime, ColdFusion decides whether to use cached classes based on template timestamps and settings like Trusted Cache.
Where compiled classes live
You will find compiled templates under the web context’s cfclasses folder. The exact location depends on your installation:
- Standalone/server install: under the ColdFusion instance’s web context (WEB-INF/cfclasses).
- EAR/WAR Deployment: inside the deployed application’s WEB-INF/cfclasses.
- Multiple instances: each instance maintains its own cfclasses directory.
- The authoritative path is displayed in ColdFusion Administrator > Settings Summary (look for Template Cache Directory and Component Cache).
Example table of typical paths (confirm on your system):
| Install type | Typical cfclasses path (example) |
|---|---|
| Server (Windows) | C:\ColdFusion2023\cfusion\wwwroot\WEB-INF\cfclasses |
| Server (Linux) | /opt/ColdFusion2023/cfusion/wwwroot/WEB-INF/cfclasses |
| EAR/WAR on external app server |
Tip: Always rely on the Settings Summary page for the exact paths in your environment.
Template caching vs. Trusted Cache vs. Component Cache
- Template caching: Stores compiled CFML classes; ColdFusion may recompile when source timestamps change.
- Trusted Cache: When enabled, CF trusts cached templates and doesn’t check source timestamps on each request, boosting Performance. After upgrades, it should be temporarily disabled or carefully managed during recompilation.
- Component Cache: Caches CFC introspection data and improves performance of component lookups. It can be cleared/rebuilt Post-upgrade.
Adobe ColdFusion vs. Lucee (brief note)
While this guide focuses on Adobe ColdFusion, Lucee also compiles CFML to Java. Lucee stores compiled classes under WEB-INF/lucee and offers precompile options in its admin. Paths and tools differ, but the concepts—clearing caches, precompiling, and warming up—are similar.
Step-by-step guide to Recompile templates
Step 1: Confirm the upgrade and hotfixes
- Confirm ColdFusion version and update level in Administrator > System Information.
- Apply all required hotfixes and restart the ColdFusion service.
- Verify Java version and that CF is using the expected JVM (cfusion/bin/jvm.config).
Practical check: Review coldfusion-out.log, application.log, and update logs for any startup errors.
Step 2: Set Caching strategy for the recompilation window
- If Trusted Cache is enabled in production, plan to temporarily disable it during warm-up to allow recompilation, then re-enable it afterward.
- Ensure “Save class files” is enabled so compiled templates persist in cfclasses (Administrator > Caching).
Tip: Document your pre-upgrade caching settings so you can restore them afterward.
Step 3: Stop ColdFusion and back up cfclasses
- Stop ColdFusion to avoid file locks and partial writes.
- Back up the cfclasses directory for safety (optional, but useful for rollback Comparison).
- Delete the contents of cfclasses to prevent stale classes from being used.
Commands (adjust paths):
Windows (PowerShell):
Stop-Service -Name ColdFusion2023
Copy-Item “C:\ColdFusion2023\cfusion\wwwroot\WEB-INF\cfclasses” “D:\backups\cfclasses_bak” -Recurse
Remove-Item “C:\ColdFusion2023\cfusion\wwwroot\WEB-INF\cfclasses*” -Recurse -Force
Start-Service -Name ColdFusion2023
Linux:
sudo systemctl stop coldfusion2023
sudo cp -a /opt/ColdFusion2023/cfusion/wwwroot/WEB-INF/cfclasses /opt/backups/cfclasses_bak
sudo rm -rf /opt/ColdFusion2023/cfusion/wwwroot/WEB-INF/cfclasses/*
sudo systemctl start coldfusion2023
Why stop CF? To avoid Race conditions and ensure a clean slate.
Step 4: Precompile with cfcompile (optional but recommended)
ColdFusion bundles a cfcompile utility to compile CFML without waiting for first requests.
- Location:
/cfusion/bin/cfcompile.{bat|sh} - Use cfcompile -help in your environment to see supported switches.
- Common approach: specify the webroot and the directory to precompile recursively.
Examples:
Windows:
“C:\ColdFusion2023\cfusion\bin\cfcompile.bat” ^
-webroot “C:\inetpub\wwwroot” ^
-dir “C:\inetpub\wwwroot\myapp” ^
-recurse
Linux:
/opt/ColdFusion2023/cfusion/bin/cfcompile.sh \
-webroot “/var/www/html” \
-dir “/var/www/html/myapp” \
-recurse
Notes:
- If you have multiple roots or virtual directories, run cfcompile per root or define CF mappings consistently.
- Some apps may require Application.cfc to load for certain includes/mappings; consider a warm-up crawl in addition to cfcompile.
Step 5: Warm up the application by crawling URLs
Even with cfcompile, runtime code paths, dynamic includes, and conditionals might compile lazily. Warm up critical routes.
Simple cURL loop (Linux/macOS):
!/usr/bin/env bash
BASE=”https://www.example.com”
declare -a paths=(
“/”
“/login.cfm”
“/app/dashboard.cfm”
“/services/api/status.cfm”
“/reports/monthly.cfm?y=2025&m=09”
)
for p in “${paths[@]}”; do
echo “Warming $BASE$p”
curl -sk “$BASE$p” > /dev/null
done
PowerShell (Windows):
$Base = “https://www.example.com”
$Paths = @(
“/”,
“/login.cfm”,
“/app/dashboard.cfm”,
“/services/api/status.cfm”,
“/reports/monthly.cfm?y=2025&m=09”
)
foreach ($p in $Paths) {
Write-Host “Warming $Base$p”
Invoke-WebRequest -Uri “$Base$p” -UseBasicParsing | Out-Null
}
Tips:
- Include authenticated flows using a session cookie or a pre-generated token.
- Use JMeter or k6 for broader coverage and concurrency to simulate real workload.
- Monitor logs for compilation errors during warm-up.
Step 6: Re-enable Trusted Cache (if you use it) and finalize caching
- If Trusted Cache was disabled, turn it back on to avoid runtime timestamp checks.
- Confirm “Save class files” remains enabled.
- If using Component Cache, clear and rebuild it by hitting critical CFC endpoints or restarting CF once more after warm-up.
Step 7: Validate connectors and mappings
- Ensure the web server connector (wsconfig) matches your CF version. Re-run wsconfig if you upgraded ColdFusion’s underlying Tomcat or moved instances.
- Confirm CF mappings in Administrator and Application.cfc are consistent. Mismatch here can cause “template not found” or partial compilation.
Step 8: Check logs and fix any compile-time errors
Scan:
- application.log for errors thrown during compilation and first hits.
- coldfusion-out.log or console logs for warnings.
- exception.log for stack traces indicating classloader issues.
Resolve issues and rerun warm-up loops for the affected paths.
Step 9: Multi-instance and multi-site environments
Repeat steps per instance and per site/webroot:
- Each instance has its own cfclasses.
- Load balancers: drain nodes, recompile and warm up each node, then rotate traffic.
Step 10: Automate for future upgrades
- Script cfclasses cleanup, cfcompile, and warm-up steps in your CI/CD pipeline.
- Maintain a canonical warm-up URL list (commit to repo).
- Consider a health endpoint that verifies compilation of critical templates.
Configuration examples and helpful snippets
Application.cfc settings that influence caching
Example Application.cfc (excerpt):
component {
this.name = “MyApp_Prod”;
this.sessionManagement = true;
// Consider enabling component cache if stable:
this.componentCache = true;
// If you manage mappings here, ensure they match Admin mappings:
this.mappings = {
“/lib” = expandPath(“/shared/lib”),
“/views” = expandPath(“/app/views”)
};
// Optional during warm-up: define onApplicationStart tasks
function onApplicationStart() {
// Preload services or metadata here if needed
return true;
}
}
Guidance:
- Keep mappings authoritative and consistent across environments.
- Avoid environment-specific paths hardcoded in code; use environment variables or central config.
Programmatic warm-up from ColdFusion
If you prefer an in-app warm-up (e.g., via a scheduled task):
urls = [
“/”,
“/login.cfm”,
“/app/dashboard.cfm”,
“/reports/monthly.cfm?y=2025&m=09”
];
base = “https://www.example.com”;
for (p in urls) {
try {
http method=”get” url=”#base##p#” timeout=30 result=”res”;
writeLog(type=”information”, file=”warmup”, text=”Warmed #p# -> #res.statusCode#”);
} catch (any e) {
writeLog(type=”error”, file=”warmup”, text=”Warm-up failed for #p#: #e.message#”);
}
}
ORM-specific note (if you use Hibernate/CF ORM)
Upgrades can require ORM rebuild:
- Use ormReload() after startup or in onApplicationStart to rebuild mappings.
- Check datasource compatibility and driver versions.
- Expect longer warm-up if ORM entities are numerous.
Risks, Common Issues, and How to Avoid Them
-
Stale class files persist after upgrade
- Cause: Not clearing cfclasses or Trusted Cache left on throughout Deployment.
- Avoid: Stop CF, clear cfclasses, recompile, warm up, then enable Trusted Cache.
-
Permission and locking errors
- Cause: ColdFusion service account lacks permissions on cfclasses or webroot.
- Avoid: Grant read/write to the CF service user. Stop the service before deletion.
-
Java/CF version mismatch
- Cause: Pointing CF to unsupported JVM or outdated update level.
- Avoid: Confirm Java support matrix for your CF version; update jvm.config carefully.
-
Connector mismatch (IIS/Apache)
- Cause: Using an old wsconfig after upgrading CF/Tomcat.
- Avoid: Re-run wsconfig; rebind to the new instance; test multiple sites.
-
Memory spikes and GC pauses during warm-up
- Cause: Bulk compilation and ORM initialization.
- Avoid: Increase heap temporarily; perform staged warm-up; compile off-peak.
-
Mapping and include Path errors
- Cause: Changes in Application.cfc mappings or Administrator mappings Post-upgrade.
- Avoid: Align mappings; test dynamic includes and custom tag paths.
-
Component cache inconsistencies
- Cause: Metadata changed but component cache not refreshed.
- Avoid: Clear component cache (restart CF or flush) and warm up component-dependent routes.
-
Security sandbox or lockdown conflicts
- Cause: Lockdown tool or sandbox denies writes to cfclasses or reads to new directories.
- Avoid: Update sandbox/lockdown policies to allow necessary paths and operations.
Post-Migration Checklist
-
Caching and compilation
- cfclasses cleared and repopulated.
- Trusted Cache set to your target production state (usually enabled).
- Save class files enabled.
-
Functional validation
- Warm-up crawl completes without 500s or compilation errors.
- Critical user journeys (login, search, checkout, reporting) verified.
- API endpoints return expected status codes and payloads.
-
Performance
- First-request latency normalized (no excessive cold starts).
- CPU/memory stable post-warm-up; GC logs within expected ranges.
-
Logs and monitoring
- application.log and exception.log clean.
- No unexpected stack traces for MissingInclude, InvalidToken, or classloader issues.
- APM or server monitors show normal throughput and response times.
-
Connectors and Networking
- Web server connector healthy; no 500.0 or 503 from IIS/Apache.
- All sites/virtual hosts point to correct CF instance.
-
ORM (if applicable)
- ormReload performed successfully.
- No datasource or dialect errors.
-
Multi-node environments
- Each node recompiled and warmed.
- Load balancer re-enabled and health checks passing.
-
Documentation
- Record versions, steps executed, and any deviations.
- Update runbooks with refined warm-up lists and scripts.
Additional tips and Best practices
- Blue/green deployment: Recompile and warm up on the green environment, then switch traffic.
- Scheduled warm-up tasks: Keep a daily off-peak warm-up to keep caches hot after restarts.
- CI/CD Integration: Automate cfcompile and URL warm-up in your deployment pipeline.
- Observe “Save class files”: Persisted classes speed recovery after restarts and container reschedules.
- Version-aware warm-up lists: Maintain per-app, per-version warm-up paths.
FAQ
Do I need downtime to Recompile templates?
Not necessarily. If you can route traffic away (blue/green or per-node draining), you can recompile and warm up without full downtime. For single-node setups, brief downtime to clear cfclasses and restart is safer.
What’s the difference between clearing the template cache and deleting cfclasses?
“Clearing template cache” in Administrator primarily affects in-memory caches and runtime trust behavior. Deleting the cfclasses directory removes on-disk compiled classes, forcing full recompilation to disk. After an upgrade, deleting cfclasses is the most reliable reset.
Should I use cfcompile or just rely on warm-up traffic?
Use both if possible. cfcompile accelerates bulk compilation and catches Syntax issues early. A warm-up crawl ensures runtime paths, dynamic includes, and conditional logic also compile and execute as expected.
How do I handle multiple instances or multiple webroots?
Repeat the process for each instance and each webroot. Each instance has its own cfclasses directory and its own ColdFusion Administrator settings. For load-balanced clusters, remove a node from the pool, recompile/warm it, then return it to service.
Does this approach apply to Lucee too?
The concepts do: clear compiled classes, precompile, and warm up. But tools and paths differ (Lucee often uses WEB-INF/lucee). Consult Lucee Admin for its precompile Features and cache locations, and follow Lucee-specific documentation.
