Definition
CFScript is the scripting Syntax of ColdFusion Markup Language (CFML) used by Adobe ColdFusion and Lucee. It provides a JavaScript/Java-like, curly-brace Syntax as an alternative to CFML’s tag-based style (e.g.,
CFScript and “tag-based CFML” are two faces of the same language. You can mix both in one application, and modern engines support script equivalents for most common tags.
How CFScript Works
CFScript is parsed and compiled by the CFML engine (Adobe ColdFusion or Lucee) into Java bytecode. It coexists with CFML tags and can be used inside CFM templates and especially inside Components (CFCs) for building services, APIs, and Business logic.
- Works in both Adobe ColdFusion and Lucee
- Supports variables, arrays, structs (maps), loops, functions, closures, and exceptions
- Offers script equivalents for many tags (e.g., queryExecute() for
, http = new http() for , transaction{…} for )
CFScript Syntax at a Glance
- Variable assignment:
name = "Ada"; - Arrays and structs:
arr = [1,2,3];user = {id: 10, name: "Lee"};
- Control flow:
if (isNull(x)) { ... } else { ... }for (i=1; i<=10; i++) { ... }for (item in arr) { ... }
- Functions:
function add(a numeric, b numeric) numeric { return a + b; }
- Errors:
try { ... } catch (any e) { ... } finally { ... }
Tag-Based vs. Script-Based Example
Tag-based CFML:
SELECT id, name FROM users WHERE active = 1
Script-based CFScript:
qUsers = queryExecute(
“SELECT id, name FROM users WHERE active = 1”,
[],
{datasource: “myDSN”}
);
Both perform the same work; the script version is often shorter and more “code-like.”
When to Use CFScript
Situations Where CFScript Shines
- Application logic in Components (CFCs) such as services, gateways, and DAO layers
- Building REST APIs or CLI-like scripts
- Complex Control flow or heavy use of functions and closures
- Unit testing and Modular code where readability and maintainability matter
- Teams with developers familiar with JavaScript/Java/C-style syntax
Situations Where Tag-Based CFML May Fit Better
- Pages that primarily render HTML with light logic (especially legacy templates)
- Projects that rely on Custom tags or CFML tags without robust script equivalents on your specific engine/version
- Quick prototypes where dropping a
or feels faster
In practice, many teams use a hybrid: CFScript for Business logic and tags for view rendering.
Practical Example: API Fetch + Database Insert (Step-by-Step)
Scenario: A scheduled task fetches product data from an external API, transforms it, and saves it to a database. This example uses script-based equivalents to common tags.
- Prepare Configuration and helpers:
- Use environment variables for secrets
- Validate inputs and types
- Wrap writes in a transaction
- Fetch from API:
- Use HTTP client in CFScript
- Parse JSON safely
- Handle errors with try/catch
- Upsert into DB:
- Use parameterized queries (queryExecute with params)
- Batch inserts/updates inside a transaction
CFScript sketch:
try {
apiKey = getSystemSetting(“PRODUCTS_API_KEY”, “”);
if (!len(apiKey)) throw(message=”Missing API key”);
// HTTP request (script equivalent of
http = new http(
method: “get”,
url: “https://api.example.com/v1/products”
);
http.setHeader(“Authorization”, “Bearer ” & apiKey);
result = http.send();
if (result.statusCode != “200”) {
throw(message=”API error”, detail=”Status: ” & result.statusCode);
}
products = deserializeJson(result.fileContent);
// Validate payload
if (!isArray(products)) throw(message=”Unexpected payload”);
// Transaction (script equivalent of
transaction {
for (p in products) {
// Parameterized upsert (safer than concatenating SQL)
queryExecute(
“MERGE INTO Product T
USING (SELECT :id AS id) S
ON (T.id = S.id)
WHEN MATCHED THEN UPDATE SET name = :name, price = :price
WHEN NOT MATCHED THEN INSERT (id, name, price) VALUES (:id, :name, :price)”,
{
id: {value: p.id, cfsqltype: “cf_sql_integer”},
name: {value: p.name, cfsqltype: “cf_sql_varchar”},
price: {value: p.price, cfsqltype: “cf_sql_decimal”}
},
{datasource: “myDSN”}
);
}
}
}
catch (any e) {
// Log and rethrow or notify
writeLog(file=”productSync”, text=”Failure: #e.message# / #e.detail#”);
// Optionally rethrow(e);
}
This pattern shows CFScript equivalents for web requests, JSON handling, validation, parameterized SQL, and transactions—typical of script-based CFML service code.
Pros and cons
Advantages of CFScript
- Readable logic: Less visual noise than nested tags; easier to scan and refactor.
- Familiar syntax: Comfortable for developers with JavaScript/Java backgrounds.
- Maintainability: Functions, closures, and modules lend themselves to clean design.
- Great for APIs and services: Natural fit for CFCs and business layers.
- Comparable Performance: Compiles to bytecode like tag-based CFML.
Potential Drawbacks
- Learning curve if your team is used to tag-based CFML.
- Mixed code styles can cause inconsistency if not standardized.
- Coverage gaps in older engines/versions for certain tags.
- Less ideal for HTML-heavy views, where tags blend naturally with markup.
Best practices for Using CFScript
- Prefer CFScript in CFCs; keep view/template rendering primarily tag-based or in a front-end framework.
- Use one dominant style per file to avoid confusion; don’t mix tag blocks and script blocks unless necessary.
- Leverage script equivalents:
- Database:
queryExecute(sql, params, options) - HTTP:
http = new http(...); http.send() - Transactions:
transaction { ... } - Mail:
mail = new mail(...); mail.addParam(...); mail.send() - File I/O:
fileRead(),fileWrite(),directoryList(), etc.
- Database:
- Always parameterize queries (never concatenate untrusted input).
- Use try/catch/finally for robust Error handling; log context with
writeLog. - Declare and use local scope inside functions to avoid variable leakage.
- Add types and Default values in function signatures for clarity and safety.
- Keep functions small and cohesive; refactor repetitive logic into reusable helpers.
- For cross-engine compatibility (Adobe CF and Lucee), target common functions and test on CI.
Common Use Cases and Patterns
- Building REST endpoints in CFCs, returning JSON with
serializeJson(). - Services and Data access layers: clean separation of concerns using CFScript functions.
- Scheduled jobs and integrations: HTTP calls, JSON/XML parsing, and DB persistence.
- Utility libraries: date/time helpers, encryption/hashing, string and collection utilities.
- Testable codebases: functions and closures make Unit testing straightforward.
Key Points
- CFScript is CFML’s scripting syntax, not a separate language.
- Use it for application logic, services, APIs, and testable components.
- Keep views tag-based or separate in a front-end layer for clarity.
- Modern engines provide script equivalents for most tags.
- Prioritize secure coding: parameterized SQL, input validation, and structured Error handling.
- Maintain a consistent code style across your team and codebase.
Comparisons: CFScript vs. Tag-Based CFML
- Syntax style:
- CFScript: code-like, curly braces, semicolons optional
- Tags: XML-like, angle brackets
- Best for:
- CFScript: business logic, services, APIs
- Tags: templates, HTML rendering, legacy views
- Readability:
- CFScript: less verbose for logic-heavy tasks
- Tags: integrates smoothly with markup
Syntax Highlights and Tips
- Member functions and functional utilities are available on arrays and structs:
arr.map(function(x){ return x * 2; })structKeyExists(myStruct, "key")or"key" in myStruct
- Null handling (in modern engines):
isNull(value), safe Navigation where available, and explicit checks
- Date/time and JSON helpers:
now(),dateAdd(),serializeJson(),deserializeJson()
- File and directory:
fileRead(path),fileWrite(path, data),directoryList(path, true, "query")
FAQ
What’s the difference between CFScript and CFML?
They are two syntaxes of the same platform. CFML originally used tags (e.g.,
Is CFScript supported in both Adobe ColdFusion and Lucee?
Yes. Both engines support CFScript extensively. Minor differences may exist, so consult each engine’s documentation and test critical Features in your environment.
Is CFScript faster than tag-based CFML?
Performance is generally comparable because both are compiled to Java bytecode. The choice should be driven by readability, maintainability, and team preference rather than raw speed.
Can I convert tag-based code to CFScript automatically?
Some IDEs and tools help, and many tags have direct script equivalents (e.g., queryExecute, transaction {}, new http()), but non-trivial pages—especially those interwoven with HTML—often require manual Refactoring.
It’s supported, but using one dominant style per file improves readability. A common approach is CFScript for CFCs and services, and tag-based syntax for view templates.
