Environments and Configuration Overrides
LuCLI supports multiple environments (such as dev, staging, and prod) inside a single lucee.json. Environment blocks let you override the base configuration without duplicating everything.
This page is the canonical reference for configuration load order and deepâmerge behaviour. It explains how environments work, how values are merged, and how to use them safely.
Base vs. environment configuration
A typical lucee.json:
{
"name": "my-app",
"port": 8080,
"jvm": {
"maxMemory": "512m",
"minMemory": "128m"
},
"monitoring": {
"enabled": true,
"jmx": { "port": 8999 }
},
"environments": {
"prod": {
"port": 80,
"jvm": {
"maxMemory": "2048m"
},
"monitoring": {
"enabled": false
},
"openBrowser": false
},
"dev": {
"port": 8081,
"monitoring": {
"jmx": { "port": 9000 }
}
},
"staging": {
"port": 8082,
"jvm": {
"maxMemory": "1024m"
}
}
}
}
- Topâlevel keys define the base configuration.
- Each entry under
environmentscontains overrides for that environment.
When you start a server with --env, LuCLI merges the chosen environment onto the base config.
Starting with an environment
Use the --env flag:
# Production configuration
lucli server start --env=prod
# Development configuration
lucli server start --env=dev
# Staging configuration
lucli server start --env=staging
You can also preview the merged configuration:
lucli server start --env=prod --dry-run
This shows the final, environmentâaware configuration LuCLI will use before actually starting the server.
Configuration load order
When an environment is specified, LuCLI builds the effective configuration in this order:
- LuCLI defaults (builtâin).
- External configuration file (if
configurationFileis set). - Base
lucee.json(topâlevel keys). - Environment overrides from
environments.<env>.
Each step overrides the previous one, following the deepâmerge rules below.
Deep merge behaviour
Environment entries are deepâmerged with the base config:
- Objects (like
jvm,monitoring) are merged recursively. - Scalars (strings, numbers, booleans) replace the base value.
- Arrays are replaced as a whole (not merged entryâbyâentry).
- Null removes the corresponding base value.
Example
Given the config above:
-
Base (no
--env)port = 8080jvm.maxMemory = 512m,jvm.minMemory = 128mmonitoring.enabled = true,monitoring.jmx.port = 8999
-
--env=prodport = 80(overrides 8080)jvm.maxMemory = 2048m(overrides),jvm.minMemory = 128m(inherited)monitoring.enabled = false(overrides),monitoring.jmx.port = 8999(inherited)openBrowser = false(overrides base value or default)
-
--env=devport = 8081(overrides 8080)jvmunchanged from base (512m / 128m)monitoring.enabled = true(inherited)monitoring.jmx.port = 9000(overrides8999)
-
--env=stagingport = 8082jvm.maxMemory = 1024m(overrides),jvm.minMemory = 128m(inherited)monitoringblock inherited from base
Environment persistence & status
When you start a server with an environment, LuCLI remembers it for that server instance. Youâll see it in listings:
lucli server list
Example output:
my-app [prod] RUNNING 12345 80
my-app [dev] STOPPED 8081
other-app RUNNING 12346 8080
And in status:
lucli server status my-app
Which includes:
Server Name: my-app [env: prod]
Status: RUNNING
Port: 80
This makes it obvious which environment a running server is using.
Invalid environments
If you pass an environment name that does not exist in lucee.json, LuCLI fails fast with a clear error and lists the available environments:
lucli server start --env=invalid
Youâll see:
â Environment 'invalid' not found in lucee.json
Available environments: prod, dev, staging
Typical workflows
Development vs. production
- Keep base settings close to your local development defaults.
- Use
environments.prodto:- Change ports (e.g. 80 instead of 8080).
- Increase memory limits.
- Disable autoâopening the browser.
- Disable monitoring or debugging features.
Staging / preâproduction
Add a staging environment that:
- Uses ports and memory closer to production.
- Keeps some debug or logging features enabled.
- Shares most other settings with
prodvia inheritance.
CI / automation
In CI pipelines:
- Use
--envto test the exact configuration that will run in a given environment. - Combine with
--dry-runto validate configuration without starting a server:
lucli server start --env=prod --dry-run --include-all
This is ideal for configuration validation steps in your pipeline.
For the full list of available settings, see
Server Configuration.
For information on how environments interact with locking, see
Server Locking.