Earlier lessons already touched several scopes individually — var/Local and Arguments in the Functions module, Variables and This inside a CFC in the OOP module. This lesson is the architectural map: every scope in one place, what each one is actually for, and the principle that decides which one to reach for.
A scope is just a named container for variables, with its own rules for who can see it and how long it lives. Picking the right one is a design decision, not a technicality — the wrong scope choice is one of the most common sources of real bugs in CFML applications.
Learning Objectives
After completing this lesson, you'll be able to:
- Name every ColdFusion scope and its lifetime, from function-local to server-wide.
- Apply the "smallest scope that fits" principle when choosing between Request, Session, and Application.
- Explain the concurrency risk that comes with sharing data across users in the Application scope.
- Know which scopes hold external, user-supplied input, and why that matters.
Every Scope, at a Glance
| Scope | Lifetime | Shared across users? | Typical use |
|---|---|---|---|
| Local (var) | One function call | No | Temporary working variables inside a function |
| Arguments | One function call | No | The parameters passed into a function |
| Variables | One page request (or CFC instance) | No | Default scope; private data inside a CFC |
| This | Life of a CFC instance | No (per-instance) | A CFC's public properties, reachable from outside |
| Request | One HTTP request | No | Data shared across includes/CFCs within a single request |
| Session | One visitor's active session | No (per-visitor) | Login state, shopping cart, per-user preferences |
| Application | Until the app times out or restarts | Yes — all visitors | Shared config, caches, connection pools |
| Server | Until the ColdFusion server restarts | Yes — every application | Data shared across multiple applications on the same server |
| Form | One HTTP request | No | Fields submitted from an HTML form |
| URL | One HTTP request | No | Query-string parameters |
| Cookie | Set by expiration date, stored in the browser | No (per-browser) | Small values persisted client-side across visits |
| Client | Set by timeout, stored server-side or in a cookie | No (per-client) | Similar to Session, but survives longer than a browser session |
| CGI | One HTTP request | No | Read-only request metadata (IP, user agent, headers) |
Session and Client sound similar but differ in survival: Session typically ends when the browser closes or times out from inactivity; Client is designed to persist across separate visits, days or weeks apart.
The Big Three: Application, Session, and Request
These three are where most real architectural decisions happen, since they're the scopes an application designs around deliberately (rather than scopes CFML hands you automatically, like Form or CGI).
<cfscript> // Application: shared by every visitor, until the app restarts application.supportedCurrencies = ["INR", "USD", "EUR"]; // Session: private to one visitor, across their whole visit session.cartItems = []; // Request: private to this one page load only request.pageStartTime = getTickCount(); </cfscript>
<cfset application.supportedCurrencies = ["INR", "USD", "EUR"]> <cfset session.cartItems = []> <cfset request.pageStartTime = getTickCount()>
The Principle: Smallest Scope That Fits
Prefer the smallest scope that still solves the problem: Request before Session, Session before Application. Reaching for a bigger scope than necessary isn't just messier — it creates real risk that grows with the scope's size.
| Scope | Concurrency risk | Why |
|---|---|---|
| Request | Low | Only this one request ever touches it — nothing else can race with it |
| Session | Medium | Only this one visitor's requests touch it, but a visitor can have multiple tabs/requests running at once |
| Application | High | Every visitor's every request can read and write it simultaneously — unprotected writes can corrupt shared data |
This is exactly why onSessionStart/onApplicationStart from the Application.cfc lessons used <cflock> when incrementing a shared counter in the Application scope — Session-scoped data being touched by one visitor at a time doesn't need that same protection.
The Scopes That Hold External Input
Form, URL, Cookie, and CGI all hold data that originated outside your code — typed by a user, or sent by their browser. Treat every value from these scopes as untrusted until validated, the same way the Variable Scope lesson's XSS example treated an unscoped form/URL value.
- Form — fields from a submitted HTML form (form.email, form.message)
- URL — query-string parameters (url.id, url.page)
- Cookie — values the browser sends back on every request to your domain
- CGI — read-only metadata about the request itself (cgi.remote_addr, cgi.http_user_agent)
Scope-Lookup Order
When a variable name has no explicit scope prefix, ColdFusion searches through scopes in this fixed order until it finds a match:
| Order | Scope |
|---|---|
| 1 | Local (function-local, var-declared) |
| 2 | Arguments |
| 3 | Thread local |
| 4 | Query (inside a query loop) |
| 5 | Thread |
| 6 | Variables |
| 7 | CGI |
| 8 | cffile |
| 9 | URL |
| 10 | Form |
| 11 | Cookie |
| 12 | Client |
This is exactly why unscoped form/URL variables are a real security risk, covered in depth in the Variable Scope lesson — URL is checked before Form, so an attacker can supply a URL parameter with the same name as an expected form field.
Advantages and Disadvantages
- Application scope is extremely fast to read from every request, since it's already in memory — no database round-trip needed for shared config or lookup data
- Session scope lets an application "remember" a visitor across many page loads without them logging in on every single request
- Request scope is perfectly safe to write to without locking, since only one request ever touches a given instance of it
- Application scope is shared by every visitor at once, so unsynchronized writes from concurrent requests can corrupt it, needs <cflock> for anything beyond simple reads
- Session scope consumes server memory for every active visitor, and if used carelessly for large data, that adds up across thousands of simultaneous sessions
- Overusing Application/Session for data that's really only needed for one request makes an application harder to reason about and test
Common Beginner Mistakes
Storing per-visitor data in the Application scope
Application scope is shared by everyone — storing one visitor's cart or login state there means every visitor sees (and can overwrite) it. That data belongs in Session.
Storing large or short-lived data in Session "just in case"
Every active session holds its own copy in server memory. Data that's only needed for the current request doesn't need to survive in Session — put it in Request instead.
Reading Form/URL/Cookie/CGI values as if they're safe
These four scopes all hold data that came from outside your code. Validate and (when displaying it back) encode anything from them before trusting it.
Summary
In this lesson, you covered every ColdFusion scope in one place, the "smallest scope that fits" principle for choosing between Request/Session/Application, the concurrency risk that grows with a scope's size, and which scopes hold untrusted external input.
What's Next?
The next lesson goes deep on Session scope specifically — session management, timeouts, and what actually happens behind the scenes when a visitor's session starts and ends. After that: Cookies, then Client Variables.