Migration - Upgrades

How to Migrate from ColdFusion to Lucee (Open Source)

Contents show

Why migrate from Adobe ColdFusion to Lucee (Open source)

Moving your CFML applications from Adobe ColdFusion to Lucee brings cost Savings, flexible Deployment options, and access to an active open-source ecosystem. Lucee is a high‑Performance CFML engine that runs on the JVM and is compatible with most ColdFusion code. It excels in containerized and cloud environments, supports Configuration‑as‑code, and offers a modular extension system. Teams often use this Migration as a chance to modernize: standardize on Docker, adopt CI/CD, and remove legacy dependencies.

Key benefits include:

  • Lower Licensing costs with an open-source runtime.
  • Strong Performance and stability on modern Java and Tomcat.
  • Easy Deployment using Docker, CommandBox, or native installers.
  • Community extensions for PDF, spreadsheets, caching, and Cloud services.
  • Fine‑grained control over settings per server/web context.

Prerequisites / Before You Start

Inventory, compatibility, and scope

  • List all applications, contexts (sites), and environments (dev, test, prod).
  • Record ColdFusion version(s) and update levels in use.
  • Catalog third‑party libraries (JARs), CFML frameworks (ColdBox, FW/1, Fusebox), and Custom tags/components.
  • Enumerate datasources, mail servers, caches, Scheduled tasks, Web services, REST endpoints, search collections, and file mounts.
  • Note Features with differing implementations:

Backups and export

  • Full backup of code repositories and binary assets.
  • Database backups and schema scripts.
  • Export ColdFusion Administrator settings (datasources, mail, mappings, caching).
  • Export Scheduled tasks and custom Security settings.
  • Gather SSL certificates and keystores used by your app.

Version and runtime constraints

  • Choose a Lucee version target: 5.4.x or 6.x.
  • Pick a Java version supported by your chosen Lucee image:
    • Java 11 or 17 are broadly supported and stable. Verify Lucee release notes if using newer LTS versions.
  • Servlet container: Tomcat 9/10.x is common with Lucee distributions.
  • OS and web server: IIS, Apache HTTPD, or Nginx.
  • Decide on installation type:
    • Lucee Installer (Windows/Linux), Lucee Docker images, or CommandBox (cfconfig-friendly).
  • Network and security:
    • Firewall rules for AJP/HTTP proxy.
    • Secrets management for DSNs, mail, API keys.
See also  How to Migrate ColdFusion Custom Tags to CFCs

Testing and rollout plan

  • Integration tests covering core flows and edge cases.
  • Side-by-side environment to run ColdFusion and Lucee in parallel.
  • Rollback plan with DNS or load balancer toggles.
  • Observability stack: logs, metrics, APM, and health checks.

Feature parity snapshot

Area Adobe ColdFusion Lucee (Open source) Notes
PDF (cfdocument) Built-in Extension-based Expect rendering differences; embed fonts.
Charts (cfchart) Built-in Extension-based Options/features may differ.
ORM Hibernate Hibernate (extension) Verify versions/behavior; lazy loading nuances.
Spreadsheet cfspreadsheet Spreadsheet extension Similar via Apache POI under the hood.
Search Embedded Solr External Solr/Elasticsearch Migrate collection usage.
Admin API CF Admin API Lucee Admin + CFConfig Prefer config-as-code.
Image (cfimage) Built-in Built-in Parity is good; test filters/fonts.

Step-by-step Migration guide

1) Choose your Migration strategy

  • In-place: Replace ColdFusion runtime on the same host. Fast but riskier.
  • Side-by-side: Stand up Lucee on new hosts or containers and route traffic gradually. Safest and recommended.
  • Greenfield/modernize: Containerize with Docker/CommandBox, implement CI/CD, and refactor Configuration to code.

Best practice: side-by-side or greenfield with parallel runs and feature flags.

2) Prepare a Lucee runtime

Option A: Docker (recommended)

  • Choose a Lucee official image tag compatible with your Java/Tomcat stack (e.g., lucee/lucee:6.0-light or 5.4-light).
  • Create a Dockerfile:

FROM lucee/lucee:6.0-light

Or pin to a specific tag that matches your Java/Tomcat needs.

Copy your application

COPY ./app /var/www

Optional: preload extensions (PDF, ORM, Spreadsheet) via server.json or Admin CLI

Expose Tomcat HTTP

EXPOSE 8888

Option B: CommandBox

box.json and .cfconfig.json in your repo

box install
box server start cfengine=lucee@6

Option C: Native installer

  • Use the Lucee installer on Windows/Linux. This bundles Tomcat and Lucee. Good for IIS/Apache Integration.

3) Connect your web server to Lucee

IIS (Windows) with BonCode (AJP/HTTP)

  • Install BonCode connector.
  • Configure Tomcat’s AJP connector:


  • In BonCode AJP settings, set the secret and block external access.
  • Map .cfm/.cfc/.cfml to the connector in IIS.

Apache HTTPD

  • Use mod_proxy_ajp or mod_proxy_http:

<VirtualHost :80>
ServerName example.com
ProxyPreserveHost On
ProxyPassMatch ^/(.
.cf[cm]|rest/.*)$ ajp://127.0.0.1:8009/$1
ProxyPassReverse / ajp://127.0.0.1:8009/
DocumentRoot /var/www

Nginx

location ~* .(cfm|cfc|cfml)$ {
proxy_pass http://127.0.0.1:8888;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Tip: Use mod_cfml to auto-create web contexts for virtual hosts with Lucee.

4) Move configuration: datasources, mail, caches, mappings

Prefer configuration-as-code using CFConfig (works great with CommandBox; can also export/import to Lucee).

Export from ColdFusion:

box install commandbox-cfconfig
cfconfig export from=adobe to=./.cfconfig-adobe.json

Transform/update and import into Lucee:

cfconfig import to=lucee from=./.cfconfig-adobe.json

Review and adjust:

  • Datasources: Update drivers and JDBC URLs if necessary.
  • Mail: Host, auth, SSL/TLS, timeouts.
  • Caches: Install Lucee cache extensions (EHCache, Redis, Memcached).
  • Mappings: this.mappings in Application.cfc or Lucee Admin mappings to point to code folders.
  • Extensions: Install Lucee extensions (PDF, Spreadsheet, ORM, S3, Image) via Admin or server.json.

Example server.json snippet for extensions:

{
“extensions”: [
{ “id”: “D062D72F-FE37-4B99-83D3-2E04E7DF3E65”, “version”: “latest” }, // PDF
{ “id”: “4B66A31C-597B-4513-8E84-429FF39A67F5”, “version”: “latest” } // Spreadsheet
]
}

5) Deploy your application code

  • Copy code to /var/www (Linux) or your chosen webroot. With Docker, mount as a volume during testing.
  • Ensure file permissions and ownership allow Tomcat/Lucee to read and write necessary directories (uploads, temp, logs).
  • Set this.mappings in Application.cfc for component or library paths:

component {
this.name = “MyLuceeApp”;
this.mappings[“/com”] = expandPath(“/com”);
this.sessionManagement = true;
this.sessionTimeout = createTimespan(0,0,30,0);
this.scriptProtect = “all”;
}

6) Address CFML language and tag differences

Unsupported/partial features

  • cfclient and legacy UI tags (cfform with Flash/Apptags) aren’t fully supported; replace with HTML/JS frameworks.
  • Built-in Solr/Verity not provided; replace with external Solr/Elasticsearch.
  • Some Enterprise-only Adobe features have no direct equivalents; redesign or use libraries.
See also  How to Handle Deprecated Tags During ColdFusion Upgrade

Data types and nulls

  • Lucee has stronger null support. If code assumes empty strings where null may occur, normalize:

if (isNull(user.middleName)) user.middleName = “”;

  • Compare dates and query values carefully; avoid implicit string-number coercion where ambiguous.

Query and QoQ differences

result = queryExecute(
“SELECT * FROM users WHERE email = :email”,
{ email = { value=arguments.email, cfsqltype=”cf_sql_varchar” } },
{ datasource=”AppDSN” }
);

Scope resolution and case sensitivity

  • Lucee is generally case-insensitive like CF, but be consistent with variable naming.
  • Always qualify scopes for clarity: variables.foo, application.config, request.context.

PDF, image, and charting

  • Install Lucee PDF extension. HTML-to-PDF rendering may differ from Adobe; validate CSS/print rules and embed fonts:

#htmlContent#

Admin APIs

  • Replace Adobe Admin API scripts with CFConfig or Lucee Admin CLI tasks. Treat config as code to avoid drift.

7) Rewire integrations

  • ORM/Hibernate:

    • Install Lucee ORM extension; align Hibernate config and version expectations.
    • Test lazy-loading and caching. Consider explicitly loading relationships to avoid N+1 issues.
  • Search:

    • Migrate collection operations to external Solr or Elasticsearch. Abstract search calls to a service layer.
    • Update analyzers and schema; test multi-lingual/stemming behavior.
  • Mail:

    • Validate TLS/SSL, auth methods, and timeouts. Use cfmail spooler settings in Lucee Admin if needed.
  • Caching and sessions:

    • Choose a session/caching provider (e.g., Redis) for clustering.
    • Configure Lucee session cookies: SameSite, Secure, HttpOnly.

this.sessionCookie = {
sameSite: “Lax”,
secure: true,
httpOnly: true
};

  • S3 and cloud storage:

    • Use Lucee resource providers (e.g., s3://bucket/key) via extension.
    • Migrate file I/O to resource URIs where appropriate.
  • Scheduled tasks:

    • Recreate in Lucee Admin or define via CFConfig. Consider external schedulers (cron/K8s) for resilience.
  • Web services:

    • SOAP/WSDL and REST endpoints usually work, but re-generate stubs and test SSL ciphers and timeouts.

8) Logging and Error handling

  • Configure application-level error pages and central exception handling:

component {
function onError(exception, eventName) {
// log
writeLog(type=”error”, text=serializeJSON(exception));
// user-friendly response
if (isDefined(“request.isApi”)) {
cfcontent(type=”application/json”, reset=true);
writeOutput( serializeJSON({ error=true, message=”Unexpected error.” }) );
} else {
include “/errors/500.cfm”;
}
}
}

  • Route Lucee/Tomcat logs to your logging stack. Standardize log formats (JSON if using centralized logging).

9) Performance tuning

  • JVM: Set heap sizes and GC suitable for your workload (e.g., G1GC, region sizes).
  • Tomcat: Tune thread pools, connection limits, keepalive.
  • Lucee:
    • Enable template caching and function/class caching.
    • Audit CFML hotspots with APM/profiling.
    • Use queryparam or queryExecute bind parameters for DB performance and security.
  • Static assets: Offload to CDN, ensure proper caching headers.

10) Automated tests and parallel runs

  • Run unit/integration tests under Lucee first.
  • Start a shadow environment mirroring production traffic (read-only mode if needed).
  • Compare logs, Performance metrics, and user behavior. Use canary releases or percentage-based routing to shift traffic gradually.

Risks, Common Issues, and How to Avoid Them

  • Feature mismatches (PDF, charts, old UI tags)
    • Mitigation: Install relevant Lucee extensions; test critical documents; replace legacy UI tags with HTML/JS.
  • ORM divergences
    • Mitigation: Pin Hibernate versions via extension; add integration tests around lazy loading and transactions.
  • Config drift between environments
    • Mitigation: Adopt CFConfig and keep configuration under Version control; avoid manual admin changes.
  • Connector/security misconfiguration
    • Mitigation: Use AJP secrets or proxy over HTTP on loopback only; validate TLS; restrict admin interfaces by IP.
  • Charset/locale differences
    • Mitigation: Set consistent encoding (UTF-8) in Application.cfc, web server, and database connections.
  • Timezone handling
    • Mitigation: Standardize on UTC in servers and databases; format for users at the edge.
  • Null/empty divergence
    • Mitigation: Normalize nulls in Data access layers; add guards for optional fields.
  • Cached code/classes during deployment
    • Mitigation: Enable smooth restarts, clear template cache on deploy, or use versioned container images.
See also  How to Move ColdFusion Apps to a New Domain or Host

Post-Migration Checklist / Validation Steps

Functional

  • All routes render without 500s; key pages and forms work.
  • Authentication/authorization flows succeed; session stickiness validated.
  • File uploads/downloads, image transformations, and PDF generation verified.
  • Emails send with correct encoding and attachments.

Data

  • All datasources connect; CRUD operations work; migrations applied.
  • Transactions and isolation behave as expected; no deadlocks/regressions.

Integrations

  • REST/SOAP endpoints pass contract tests and handle timeouts gracefully.
  • Search returning expected results; analyzers, relevancy, and pagination tested.
  • Caching behaves (evictions, TTLs); Session replication works in a cluster.

Performance

  • Baseline response times and throughput match or exceed ColdFusion.
  • No unexpected memory growth or GC pauses; heap/threads within limits.
  • Load tests with production-like data pass.

Security

  • Admin endpoints restricted and/or disabled in production.
  • Secure headers (CSP, HSTS, X-Frame-Options) present via web server or app.
  • Session cookies: Secure, HttpOnly, SameSite set appropriately.
  • Secrets stored in environment variables or a vault, not in code.

Operations

  • Logs centralized and searchable with correlation IDs.
  • Health endpoints wired into monitoring; alerts configured for error rates, latency, and resource exhaustion.
  • Backups and restore tested; rollback plan validated.

Governance

  • Documentation updated: runbooks, diagrams, developer guides.
  • CI/CD pipeline includes linting, tests, security scanning, and image signing.
  • License Compliance checked for all extensions and third-party libraries.

Practical Configuration Examples

Docker Compose for Lucee with PostgreSQL and Redis

version: “3.8”
services:
web:
image: lucee/lucee:6.0-light
ports:

  • “8080:8888”
    environment:
  • LUCEE_EXTENSIONS=”pdf,orm,spreadsheet”
    volumes:
  • ./app:/var/www
    depends_on:
  • db
  • cache
    db:
    image: postgres:15
    environment:
  • POSTGRES_PASSWORD=secret
    cache:
    image: redis:7

CFConfig sample for Lucee

{
“datasources”: {
“AppDSN”: {
“class”: “org.postgresql.Driver”,
“connectionString”: “jdbc:postgresql://db:5432/appdb”,
“username”: “appuser”,
“password”: “ENV:DB_PASSWORD”,
“validate”: true
}
},
“mailservers”: [
{
“server”: “smtp.mailhost.local”,
“username”: “mailer”,
“password”: “ENV:SMTP_PASSWORD”,
“ssl”: true,
“port”: 465
}
],
“caches”: {
“object”: { “class”: “lucee.extension.io.cache.redis.RedisCache”, “custom”: { “host”: “cache”, “port”: “6379” } }
},
“mappings”: {
“/com”: { “physical”: “/var/www/com” }
}
}

Application.cfc essentials for Lucee

component {

this.name = “MyApp”;
this.sessionManagement = true;
this.sessionCookie = { secure:true, httpOnly:true, sameSite:”Lax” };
this.charset = “utf-8”;
this.locale = “en_US”;
this.timezone = “UTC”;
this.mappings[“/lib”] = expandPath(“/lib”);

function onApplicationStart(){
application.startedAt = now();
return true;
}

function onRequestStart(targetPage){
request.requestId = createUUID();
}

function onError(e, eventName){
writeLog(type=”error”, text=serializeJSON({ event=eventName, message=e.message, detail=e.detail }));
include “/errors/500.cfm”;
}
}


FAQ

Can I run Adobe ColdFusion and Lucee side-by-side during migration?

Yes. Many teams run a parallel Lucee environment and mirror traffic using a staging DNS or canary rules in the load balancer. This lets you validate functionality and performance safely before switching production traffic.

How compatible is Lucee with my existing CFML code?

Compatibility is high for core CFML. Differences typically involve enterprise features, PDF/chart rendering nuances, older UI tags, and Admin API scripts. Most issues are resolved by installing Lucee extensions, modest refactors, or using modern equivalents (e.g., external Solr/Elasticsearch).

Do I need to change my database drivers or SQL?

Often you can keep your SQL as-is. Validate JDBC drivers for your database and ensure parameterized queries via queryExecute or cfquery with cfqueryparam. Watch for Query-of-Queries differences and date/time handling.

What’s the recommended way to manage Lucee configuration?

Use configuration-as-code. CFConfig allows you to export/import datasources, mail, caches, mappings, and scheduled tasks, keeping settings under Version control and consistent across environments. Avoid manual changes in Admin for production.

Is Lucee suitable for containerized and cloud deployments?

Absolutely. Lucee runs well in Docker and Kubernetes. Use official Lucee images or CommandBox-based images, keep config in code, externalize sessions/caches, and rely on health checks, structured logs, and immutable builds for reliable operations.

About the author

Aaron Longnion

Aaron Longnion

Hey there! I'm Aaron Longnion — an Internet technologist, web software engineer, and ColdFusion expert with more than 24 years of experience. Over the years, I've had the privilege of working with some of the most exciting and fast-growing companies out there, including lynda.com, HomeAway, landsofamerica.com (CoStar Group), and Adobe.com.

I'm a full-stack developer at heart, but what really drives me is designing and building internet architectures that are highly scalable, cost-effective, and fault-tolerant — solutions built to handle rapid growth and stay ahead of the curve.