How AUTH0_PRESERVE_KEYWORDS Preserves Keyword Markers During Export in Auth0 Deploy CLI
Setting AUTH0_PRESERVE_KEYWORDS=true prevents the Auth0 Deploy CLI from overwriting keyword placeholders like ##DOMAIN## with live tenant values during export operations, ensuring your local configuration files remain environment-agnostic and reusable.
The Auth0 Deploy CLI is an open-source tool that enables configuration-as-code management for Auth0 tenants. When running an export (or dump) operation, the CLI normally fetches the current state of your Auth0 tenant and writes those values directly to your local YAML or directory structure, destroying any placeholder markers you use for multi-environment deployments. The AUTH0_PRESERVE_KEYWORDS environment variable activates a sophisticated preservation pipeline that detects these markers in your local files and restores them to the exported output.
How Keyword Preservation Works
The preservation system operates through a multi-stage pipeline defined primarily in src/keywordPreservation.ts. This process intercepts the export flow after the CLI fetches remote assets but before the context layer writes files to disk.
Validation and Context Initialization
Before preservation begins, the context layer validates your configuration. In src/context/index.ts (lines 84‑94), the CLI checks that AUTH0_PRESERVE_KEYWORDS is enabled and that AUTH0_KEYWORD_REPLACE_MAPPINGS contains valid keyword definitions. If you enable preservation without defining mappings, the CLI aborts immediately with a clear error message preventing ambiguous operations.
Both YAML and Directory contexts propagate this flag consistently. In src/context/yaml/index.ts (lines 154‑155) and src/context/directory/index.ts (lines 92‑93), the preserveKeywords option passes into the export pipeline, triggering the preservation logic only when explicitly requested.
Address Collection and Marker Detection
The core algorithm begins with preserveKeywords (lines 34‑113 in src/keywordPreservation.ts), which traverses your local asset tree to identify every field containing keyword syntax (##KEYWORD## or @@KEYWORD@@).
- String fields: The function
doesHaveKeywordMarker(lines 27‑38) detects markers in plain strings and records the field address. - Array elements: For collections like
clientsorcustomDomains, the system builds unique addresses using resource-specific identifiers (e.g.,clients.[client_id=##CLIENT_ID##]) to ensure precise targeting even when identifiers themselves contain placeholders.
The function constructs resourceSpecificIdentifiers from the handler list (lines 45‑51), enabling the algorithm to locate the correct array index even when keyword markers appear in identifying fields like domain names or client IDs.
Remote Asset Rewriting and Comparison
For each discovered address, the preservation pipeline performs a three-way comparison:
- Transform local values: The local value undergoes
keywordReplace(line 92) to simulate what the live value should look like in the target environment. - Retrieve remote values:
getAssetsValueByAddress(lines 121‑170) fetches the actual value from the Auth0 tenant using dot-notation addressing. - Patch and warn: If the remote value differs from the keyword-replaced local value, the CLI prints a warning (lines 103‑106) and overwrites the remote asset tree with the original local value (still containing markers) via
updateAssetsByAddress(lines 126‑135).
This ensures the final output contains your placeholders rather than the live tenant values.
Configuring AUTH0_PRESERVE_KEYWORDS
Enable preservation by setting the environment variable before running your export command.
1. Define your keyword mappings
Create a .env file or export directly in your shell:
export AUTH0_KEYWORD_REPLACE_MAPPINGS='{
"DOMAIN":"myapp.dev",
"CLIENT_ID":"abc123",
"AUDIENCE":"https://api.example.com"
}'
2. Enable preservation and export
export AUTH0_PRESERVE_KEYWORDS=true
npx auth0-deploy-cli export \
-c config.json \
-f yaml \
-o ./exported/
3. Verify preserved output
Your exported files retain the markers:
# exported/tenant.yaml
customDomains:
- domain: "##DOMAIN##"
primary: true
clients:
- client_id: "##CLIENT_ID##"
name: "My API"
jwt_configuration:
audience: "##AUDIENCE##"
Special Handling and Edge Cases
The preservation algorithm includes specific logic for Auth0's complex resource relationships.
Client Grant Name Resolution
In src/keywordPreservation.ts (lines 60‑70), the system handles a critical Auth0 quirk: clientGrants require the client name rather than the client ID for keyword replacement lookups. The function converts client IDs to names early in the process, ensuring that grants referencing @@CLIENT_ID@@ resolve correctly even though the Auth0 API expects the application name in that context.
Identifier Field Updates
When an identifier field itself contains a keyword marker (e.g., a custom domain named ##DOMAIN##), the replacement process temporarily loses the "key" used to locate that resource. The algorithm compensates by updating both the raw address and the keyword-replaced address (lines 124‑135), ensuring the marker survives even when the identifying value changes between environments.
Warning Output
During export, you will see explicit warnings for each preserved field:
WARNING! The remote value with address of customDomains.[domain=myapp.dev].domain has value of "myapp.dev" but will be preserved with "##DOMAIN##" due to keyword preservation.
These notifications confirm that the system actively prevented local placeholders from being overwritten with remote values.
Summary
- Validation requirement: The CLI requires both
AUTH0_PRESERVE_KEYWORDS=trueand validAUTH0_KEYWORD_REPLACE_MAPPINGSto activate preservation, enforced insrc/context/index.ts. - Address-based preservation: The
preserveKeywordsfunction insrc/keywordPreservation.tsbuilds precise addresses for every field containing markers, handling both scalar values and complex arrays. - Remote tree patching: The system compares keyword-replaced local values against remote tenant values, warns when differences exist, and overwrites the export output with original local placeholders.
- Special case handling: Client grants use name-based lookups, and identifier fields containing markers receive dual-address updates to prevent loss during replacement.
- Format support: Works identically for both YAML (
src/context/yaml/index.ts) and Directory (src/context/directory/index.ts) export formats.
Frequently Asked Questions
What happens if I enable AUTH0_PRESERVE_KEYWORDS but forget to define AUTH0_KEYWORD_REPLACE_MAPPINGS?
The CLI will abort the export operation with a configuration error. According to the validation logic in src/context/index.ts (lines 84‑94), the presence of the preservation flag without corresponding keyword mappings constitutes an invalid state, preventing potentially destructive exports.
Does AUTH0_PRESERVE_KEYWORDS work for both YAML and Directory export formats?
Yes. The preservation pipeline integrates into both context types. In src/context/yaml/index.ts (lines 154‑155) and src/context/directory/index.ts (lines 92‑93), the flag passes through to the shared preservation logic in src/keywordPreservation.ts, ensuring consistent behavior regardless of your chosen output format.
How does the CLI handle array elements when the identifier itself is a keyword placeholder?
The algorithm builds resource-specific addresses using the raw identifier values (including markers). When getAssetsValueByAddress retrieves remote values, it attempts resolution using both the original marker-based address and the keyword-replaced version (lines 124‑135), ensuring it locates the correct element even after temporary value substitution.
Will enabling preservation slow down my export operation?
The performance impact is minimal. The preservation logic performs a single traversal of your local asset tree and targeted lookups against the remote asset object. While you will see additional warning logs in your console output, the computational overhead of the address collection and comparison in preserveKeywords (lines 34‑113) is negligible for typical tenant sizes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →