Understanding ColdFusion scopes: the Short Answer
A ColdFusion scope is a named context that determines where a variable lives, how long it persists, and who can read or modify it. When developers talk about the big three—Application, Session, and Request—they mean three distinct lifecycles:
- Application scope: shared across all users for a single application until the application restarts or times out.
- Session scope: private to a single user’s browser session, lasting until the user times out or the session is ended.
- Request scope: limited to a single HTTP request (and any code executed within that request), discarded after the request completes.
These are part of ColdFusion’s broader set of variable scopes that also includes variables, local, arguments, server, client, cookie, form, url, cgi, and this. Understanding what to store in each scope—and when—is central to building robust, secure, and performant ColdFusion applications.
Why Scopes Matter: Lifetimes and Visibility
Variable scopes encode three ideas: lifetime, visibility, and concurrency. Choose the correct scope to control how long data persists, who can see it, and whether you need synchronization.
Application scope
- Lifetime: across the life of the application (until timeout or restart).
- Visibility: shared by all requests and sessions in the same application.
- Typical use: Configuration, caches, service singletons, feature flags.
- Location:
application.prefix (e.g.,application.settings).
Example:
cfscript
// Application.cfc -> onApplicationStart()
application.settings = {
appName = “Storefront”,
currency = “USD”,
featureFlags = { showBeta = false }
};
Because the Application scope is shared, writes must be thread-safe.
Session Scope
- Lifetime: per user session (often cookie-bound via CFID/CFTOKEN or JSESSIONID).
- Visibility: only to that user’s consecutive requests.
- Typical use: authenticated user info, cart contents, CSRF tokens, preferences.
- Location:
session.prefix (e.g.,session.user).
Example:
cfscript
// After successful login
session.user = { id = 12345, role = “admin”, name = “Avery” };
Request Scope
- Lifetime: the duration of one request, including views/layouts executed within it.
- Visibility: confined to the single request thread (not shared).
- Typical use: request-level metadata, log correlation IDs, per-request caches, validator results.
- Location:
request.prefix (e.g.,request.logContext).
Example:
cfscript
request.correlationId = createUUID();
Other Common Scopes You’ll Use
- variables: Default page/component variables for a request or CFC instance. In CFC methods, use local (or
var) for function-local variables. - local: Function-local scope; prevents leakage across calls. Use
var x = ...orlocal.x = .... - arguments: Named/positional arguments passed to functions.
- server: Global to the ColdFusion server instance (shared by all apps); use sparingly and lock when writing.
- client: Client-scoped storage persisted between requests (often via cookies or server side storage); consider Privacy and size limits.
- cookie: HTTP cookies sent/received; Security-sensitive.
- url, form: Request inputs; always validate and sanitize.
- cgi: Server-provided request metadata (headers, path, method).
- this: In Application.cfc, the this scope configures the application (e.g.,
this.name,this.sessionManagement, mappings, datasources).
Scope Lookup and Precedence
When you reference an unscoped variable, ColdFusion performs scope lookup in a defined order until it finds a match. This can cause accidental “masking” and Performance overhead.
- Best practice: always prefix critical variables with their scope, e.g.,
session.user,application.services,request.ctx. - In functions, declare locals using
varorlocal.to avoid promoting variables to wider scopes.
Example of risky code:
cfscript
// BAD: unscoped could collide with form/url/cookie/variables
if (isDefined(“username”)) { / … / }
Safer alternative:
cfscript
if (structKeyExists(form, “username”)) { / … / }
Performance Implications
- Unscoped lookups are slower because ColdFusion searches multiple scopes.
- Prefixing scopes makes intent explicit and reduces CPU overhead.
- In hot paths, prefer
structKeyExists(request, "x")overisDefined("x")for clarity and speed.
Real-World Examples
cfscript
// Application.cfc
component {
this.name = “StorefrontApp”;
this.sessionManagement = true;
this.applicationTimeout = createTimespan(1,0,0,0); // 1 day
function onApplicationStart() {
application.config = {
currency = “USD”,
taxRate = 0.0875
};
application.cache = {};
}
}
Use Application for service singletons:
cfscript
if (!structKeyExists(application, “productService”)) {
lock scope=”application” type=”exclusive” timeout=”5″ {
if (!structKeyExists(application, “productService”)) {
application.productService = new com.services.ProductService();
}
}
}
Session Scope Example: Shopping Cart
cfscript
// addToCart.cfm
param name=”session.cart” default=[];
arrayAppend(session.cart, { sku=”ABC123″, qty=1, price=19.99 });
Keep objects small and serializable; avoid storing huge query results in session.
Request Scope Example: Per-Request Correlation/Logger
cfscript
// onRequestStart in Application.cfc
request.ctx = {
id = createUUID(),
startTick = getTickCount()
};
// Later in request
request.ctx.elapsed = getTickCount() – request.ctx.startTick;
Request scope is ideal for values needed across views/layouts during a single request.
Initializing Scopes with Application.cfc
Required Settings: name and Session management
cfscript
component {
this.name = “StorefrontApp”;
this.sessionManagement = true;
this.setClientCookies = true; // write session cookies automatically
this.sessionTimeout = createTimespan(0,0,30,0); // 30 minutes
this.applicationTimeout = createTimespan(1,0,0,0); // 1 day
this.mappings = { “/lib” = expandPath(“./lib”) }; // example mapping
}
- Set an explicit, stable this.name or sessions won’t persist as expected.
- Adjust sessionTimeout and applicationTimeout to your needs.
Lifecycle Methods You’ll Use Often
- onApplicationStart(): initialize
application.*values once. - onSessionStart(): set
session.*defaults, e.g.,session.csrfToken. - onRequestStart(targetPage): set
request.*values (e.g., correlation ID). - onRequestEnd(): cleanup or log with
request.*. - onSessionEnd(sessionScope, appScope): finalize or persist session data.
- onError(exception, eventName): centralized Error handling; be careful with scope reads (avoid writes to shared scopes here unless you lock).
Example:
cfscript
function onSessionStart() {
session.csrfToken = hash(createUUID() & now());
}
Thread safety and Locking
Shared scopes (Application, Server, Session) can be accessed concurrently. Use cflock for writes or non-atomic reads-modify-writes.
When to Use cflock
- Multiple requests might update
application.cachesimultaneously. - Two tabs from the same user might mutate
session.cart.
Example:
cfml
Avoiding Race conditions and Stale Reads
-
Prefer immutable Data structures or clone before mutate:
cfscript
lock scope=”application” type=”exclusive” {
var newCfg = duplicate(application.config);
newCfg.taxRate = 0.09;
application.config = newCfg;
} -
Keep critical sections small to reduce contention.
Scope Hygiene and Best practices
Always Prefix Scopes
- Use
session.user,request.ctx,application.services,url.id,form.email. - Avoid ambiguous, unscoped reads.
Var/Local Your Function Variables
cfscript
function calculateTotal(required array items) {
var total = 0; // or local.total
for (var i in items) total += i.qty * i.price;
return total;
}
Unvar’d locals can leak into component or variables scope and cause bugs.
Storing Complex Objects in Session/Application
- Safe to store CFC singletons in
application.*. - Keep session values lean and serializable; store IDs not entire datasets.
- For large caches, consider external caches (Redis, EHCache) to reduce memory bloat.
Cleaning Up and Invalidation
- Use
onSessionEndfor cleanup. - Use
applicationStop()to restart an application and refreshapplication.*. - Expire caches and rotate tokens proactively.
Differences: Adobe ColdFusion vs Lucee
- Both engines implement the same core scopes and lifecycles.
- Client storage defaults and options differ; check engine admins for datastore configuration.
- Lucee often has more flexible serialization of session/application values; still, prefer portability-friendly types.
- Some functions or admin defaults (e.g., session cookies, secure flags) vary; set cookie attributes explicitly in code for consistency.
Troubleshooting and Common pitfalls
Scope Injection and Variable Masking
- Unscoped
idmight be picked up fromurl.idwhen you meant a local variable. - Use explicit scoping and
structKeyExists(scope, "key").
Session Not Sticking
- Ensure
this.nameis consistent. - Verify
this.sessionManagement = true. - Check cookies are allowed and not blocked; if required, set
this.setClientCookies = true. - Reverse proxies or load balancers may require sticky sessions or Session replication.
Memory Bloat and Leaks
- Oversized
application.cacheorsession.cartobjects can balloon memory. - Monitor heap usage; move heavy data to external caches.
- Avoid keeping per-request or per-user large queries in shared scopes.
Reference: Scope Lifetimes at a Glance
- Server: process lifetime, shared by all apps; use rarely, lock writes.
- Application: app lifetime; config, singletons, caches (locked).
- Session: per user session; auth and preferences.
- Request: per request; context, logs, per-request caches.
- variables/local/arguments: function or page local; prefer
localin functions. - url/form/cookie/cgi: request inputs and metadata; validate and sanitize.
- client: persisted per client across requests; consider Privacy and size.
- this: application configuration in Application.cfc.
Security Considerations for Scopes
- Validate types, lengths, and patterns.
- Sanitize before use; apply parameterized queries for database work.
Protect Session Data
-
Set session cookie flags: HttpOnly, Secure, SameSite.
cfscript
cookieSet(name=”CFID”, value=cfid, httpOnly=true, secure=true, sameSite=”Lax”); -
Regenerate session identifiers after login to prevent session fixation.
CSRF Protections
- Store a CSRF token in
session.*; embed per-request token in forms; validate and then rotate or expire. - Keep CSRF verification status in
request.*to simplify middleware logic.
Code Patterns and Utilities
Safe Reads/Writes
cfscript
if (structKeyExists(session, “user”)) {
// use session.user
}
lock scope=”application” type=”exclusive” timeout=”3″ {
application.cache[key] = value;
}
Using structKeyExists and Param
cfscript
param name=”url.page” default=1 type=”numeric”;
if (structKeyExists(form, “email”) && isValid(“email”, form.email)) { … }
Defensive Copies
- Use
duplicate()when you need to modify without risking shared-state corruption:
cfscript
var cartCopy = duplicate(session.cart);
Practical Checklist
- Explicitly set
this.name,this.sessionManagement,this.sessionTimeout,this.applicationTimeout. - Always scope variables: application, session, request, local, arguments.
- Lock writes to shared scopes.
- Keep session light; store IDs rather than entire objects.
- Validate url/form/cookie inputs; never trust client data.
- Use lifecycle methods to initialize and clean up.
Frequently Asked Questions
How do I enable and configure Session scope in ColdFusion?
Set this.sessionManagement = true in Application.cfc and define this.sessionTimeout. Ensure the application has a stable this.name. Optionally set this.setClientCookies = true so ColdFusion writes CFID/CFTOKEN/JSESSIONID automatically. Example:
cfscript
this.name = “MyApp”;
this.sessionManagement = true;
this.sessionTimeout = createTimespan(0,0,30,0);
When should I use Request scope instead of Variables scope?
Use request for values that must be shared across templates, tags, or CFCs within a single request (e.g., correlation IDs, per-request caches). Use variables or local for function/page-local variables that don’t need to be visible across includes or layouts.
Do I need to lock Session scope writes?
Yes, when multiple concurrent requests from the same user might modify session.* (e.g., two tabs updating the cart). Use cflock scope="session" type="exclusive" around the minimal code that mutates the session.
What should I store in Application scope?
Store shared, read-heavy, write-rarely data: configuration, service singletons, lookup tables, small caches, feature flags. Avoid per-user data or large, highly dynamic datasets that change frequently.
What’s the difference between local, variables, and arguments scopes?
- arguments: parameters passed to a function.
- local (or
var): variables local to a function call; safest for function internals. - variables: default scope for CFC/page variables; in components, it’s effectively instance scope and persists with the CFC instance. Prefer
localinside functions to avoid leaking state.
