A CFML (ColdFusion® Markup Language) interpreter written in Rust — a single, fast, run-anywhere binary with a tiny memory footprint.
ColdFusion is a registered trademark of Adobe Inc. RustCFML is not affiliated with or endorsed by Adobe.
Try RustCFML in your browser — interactive demo running on WebAssembly.
RustCFML aims to be a compatible, fast, run-anywhere CFML engine with a minimal memory footprint and maximum performance. It is deliberately opinionated:
- A lean, stable core. We don't add things to the core that are prone to constant churn in the wider ecosystem. Reliability comes first — think of RustCFML as an LTS-style engine. It is already blazingly fast.
- Libraries over built-ins. We won't add core functions that are better served by libraries. Instead, where possible, we make the engine compatible enough to run those libraries.
- No administrator, ever. RustCFML does not have — and never will have — a ColdFusion Administrator. Configuration is file-based via
.cfconfig.json, with environment-variable substitution for secrets. - Inspired by real apps and modern deployment. We follow modern deployment practices and won't bake in CI/CD features that belong in your pipeline, not your language runtime.
- Honest about Java. There is no JVM under the hood. We provide limited Java-class shim support (faking common Java classes), but you should expect — and will find — differences.
RustCFML began as a proof of AI model capabilities by Alex Skinner, CEO of Pixl8 Group. It has been written almost entirely by AI — predominantly Claude Opus — with research and test synthesis assisted by local models.
The fastest way to start is with a prebuilt binary — no toolchain required.
-
Download a binary for your platform from the latest release (Linux x86_64/aarch64, macOS aarch64), then put it on your
PATH:chmod +x rustcfml-macos-aarch64 sudo mv rustcfml-macos-aarch64 /usr/local/bin/rustcfml
-
Run a web application — the most common way to get going. Point RustCFML at a directory of
.cfmfiles:rustcfml --serve ./mywebroot --port 8500
It serves
.cfmpages and static assets, runs theApplication.cfclifecycle, and supports sessions, URL rewriting, and file uploads. See Web Server. -
Go to production — add
--productionto enable warm in-memory caching (skips per-request filesystem checks for a 3–4× throughput gain):rustcfml --serve ./mywebroot --production
See Deployment for production mode, the sandbox/virtual filesystem, standalone binaries, and Cloudflare Workers.
You can also run a single template (rustcfml myapp.cfm), drop into a REPL (rustcfml -r), or run inline code (rustcfml -c '...'). See Getting Started for those and shebang scripts.
RustCFML compiles to a native binary with no runtime VM overhead, so it starts instantly and serves requests with a fraction of the memory of JVM-based CFML engines.
Serving a "Hello World" .cfm page in --production mode against a warmed Lucee 7 — same machine (Apple M-series), same page, Apache Bench, 8s runs. Requests/sec, higher is better:
| Concurrency | RustCFML | Lucee 7.0 | RustCFML (keep-alive) | Lucee (keep-alive) |
|---|---|---|---|---|
-c 1 |
1,908 | 1,205 | 3,118 | 1,625 |
-c 10 |
5,466 | 2,648 | 21,716 | 8,125 |
-c 50 |
6,983 | 3,503 | 25,833 | 8,085 |
-c 100 |
7,528 | 3,107 | 25,855 | 7,419 |
| RustCFML | Lucee 7.0 | |
|---|---|---|
| Memory (RSS, under load) | ~60 MB | ~560 MB |
| Startup | instant | ~15s |
RustCFML serves roughly 2–3.5× the throughput at about a tenth of the memory, with no JVM warmup. Both engines benefit from HTTP keep-alive; RustCFML scales further with it, sustaining ~26,000 req/s. See Performance for full methodology and production-mode caching.
| Topic | Description |
|---|---|
| Getting Started | Prebuilt binaries, running files, REPL, shebang scripts, building from source |
| Web Server | Serve mode, Application.cfc lifecycle, URL rewriting, distributed sessions |
| Configuration | .cfconfig.json — datasources, mappings, mail, security, caches, env vars |
| Deployment | Web app, Docker, CLI tools, Cloudflare Workers; production mode & sandbox |
| Database | queryExecute, datasources, cfqueryparam, engine specifics |
| Object Storage | S3 / R2 / MinIO — S3* functions and transparent s3:// paths |
| Native Modules | Extend a binary with first-class Rust built-ins and classes |
| Java Shims | Emulated Java classes for createObject("java", …) — what's supported and known gaps |
| Threading | cfthread on real OS threads — shared vs copied scopes, join/terminate, caveats |
| Embedding | Use the RustCFML engine from your own Rust code |
| WebAssembly | Compile to WASM; Cloudflare Workers notes |
| Architecture | Compilation pipeline and crate layout |
| Performance | Benchmarks and production-mode caching |
| Testing | Running the test suites and writing tests |
| Status | Implementation status and remaining work |
RustCFML is designed to deploy as a single artifact in several shapes — see Deployment for full detail:
-
Web application — run
--servebehind your reverse proxy, with--productionfor warm in-memory caching:rustcfml --serve ./mywebroot --production
-
Optimised Docker container — coming soon: a minimal image for containerised deployment.
-
CLI tool — compile a CFML app into a standalone command-line binary. See Deployment → CLI tools.
-
Cloudflare Workers — run RustCFML at the edge via WebAssembly. See RustCFML-Cloudflare-worker.
Production mode (warm caching) and sandbox / virtual filesystem (host isolation, embedded files) apply to both web and CLI deployments — they're documented once in Deployment.
- Complete CFML language — CFScript and tag syntax (a preprocessor converts 50+ tags to CFScript), components with inheritance and interfaces, closures, member functions, and higher-order functions across arrays, structs, queries, and lists.
- 400+ built-in functions — strings, arrays, structs, dates, math, lists, queries, JSON, XML, regex, encoding, hashing, and modern password hashing (bcrypt/scrypt/argon2).
- Batteries-included web server —
Application.cfclifecycle, sessions (in-process, Memcached, or clustered), cookies, authentication, URL rewriting, and file uploads. - Data & integration —
queryExecuteover SQLite, MySQL, PostgreSQL, and MSSQL with pooling andcftransaction;cfhttp;cfmail; and S3-compatible object storage (AWS S3, Cloudflare R2, MinIO). - Real concurrency —
cfthreadruns bodies on real OS threads with sharedapplication/request/sessionscopes andcflock. See Threading. - Run anywhere — native binaries, self-contained single-file apps, and a WebAssembly target that runs on Cloudflare Workers.
- Extensible — drop in first-class built-ins and classes written in Rust (native modules).
See Compatibility & Status for implementation status.
- Query-of-Queries (QoQ) — SQL SELECT on in-memory query objects
- Image functions, Spreadsheet functions, ORM, SOAP/WSDL, Flash/Flex, PDF, LDAP, Registry
cfschedule,cfwddx
<cfthread> bodies run on real OS threads — concurrently, on separate cores — not sequentially inline. action="join" blocks until a thread (or, with no name, all threads) completes; results land in cfthread.NAME (status, output, error, elapsedtime, plus the body's thread scope). application, server, session, and request scopes are shared live across threads (guard concurrent writes with cflock); variables is copied at spawn, and data is passed in via the thread's attributes. An error in a thread sets its status to TERMINATED without aborting the parent.
Two deliberate differences from Lucee, both arising from doing threading safely in Rust:
terminateis cooperative, not forceful. Rust can't safely kill a running thread mid-instruction (it could leave locks held or memory half-written — the reason Java deprecatedThread.stop()). Instead,terminatesets a flag the body checks at loop back-edges and then aborts. A thread spinning in a loop stops promptly; one parked in a single long call (sleep, a slow query) won't notice until it returns to a loop. It's a difference in responsiveness, not correctness.- A
cftransactioncan't span the parent↔child boundary. Its live DB connection can't be used from another thread, so a spawned thread starts with no transaction — its queries aren't part of one the parent has open, and a parent rollback won't undo them. Keep transactional work within a single thread.
Full detail, scope tables, and examples: Threading.
CFML Source (.cfm / .cfc)
→ Tag Preprocessor → CFScript → Lexer → Parser → AST → Compiler → Bytecode → VM → Output
RustCFML is a Cargo workspace of focused crates (cfml-common, cfml-compiler, cfml-codegen, cfml-vm, cfml-stdlib, cli, wasm). See Architecture for the full breakdown.
If you'd rather build it yourself (or you're contributing), you need Rust stable (>= 1.75.0) — install via rustup.rs:
git clone https://github.com/RustCFML/RustCFML.git
cd RustCFML
cargo build --release # binary at target/release/rustcfml
cargo install --path crates/cli # optional: install on your PATHSee Getting Started → Building from source for feature flags, the WebAssembly target, and the self-contained-binary build path.
Contributions are welcome.
- New here? If you haven't contributed before, please open an Issue with detail (a minimal reproducible CFML snippet, expected vs actual behaviour) before opening a PR.
- Pull requests are the preferred way to contribute a fix. A great place to start is a CFML-based test that demonstrates the behaviour (see Testing).
- Lucee is the reference for compatibility. Your test must pass on Lucee — if it doesn't, we won't accept it. RustCFML targets cfdocs.org with Lucee as the primary implementation target. (By rare exception, where Lucee allows something genuinely unreasonable, we may choose not to match it.)
See Testing for how to run the suite against both RustCFML and Lucee.
Avatars are generated automatically from the GitHub contributor graph by contrib.rocks.
- Lucee — open-source CFML engine (Java)
- BoxLang — modern CFML+ runtime (Java)
- RustPython — Python interpreter in Rust (architectural reference)
MIT