# How AUTH0_PRESERVE_KEYWORDS Preserves Keyword Markers During Export in Auth0 Deploy CLI

> Learn how AUTH0_PRESERVE_KEYWORDS=true in Auth0 Deploy CLI keeps keyword markers like ##DOMAIN## intact during export, making configurations reusable and environment-agnostic.

- Repository: [Auth0/auth0-deploy-cli](https://github.com/auth0/auth0-deploy-cli)
- Tags: how-to-guide
- Published: 2026-02-25

---

**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`](https://github.com/auth0/auth0-deploy-cli/blob/main/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`](https://github.com/auth0/auth0-deploy-cli/blob/main/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`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/context/yaml/index.ts) (lines 154‑155) and [`src/context/directory/index.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/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`](https://github.com/auth0/auth0-deploy-cli/blob/main/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 `clients` or `customDomains`, 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:

1. **Transform local values**: The local value undergoes `keywordReplace` (line 92) to simulate what the live value should look like in the target environment.
2. **Retrieve remote values**: `getAssetsValueByAddress` (lines 121‑170) fetches the actual value from the Auth0 tenant using dot-notation addressing.
3. **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:

```bash
export AUTH0_KEYWORD_REPLACE_MAPPINGS='{
  "DOMAIN":"myapp.dev",
  "CLIENT_ID":"abc123",
  "AUDIENCE":"https://api.example.com"
}'

```

**2. Enable preservation and export**

```bash
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:

```yaml

# 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`](https://github.com/auth0/auth0-deploy-cli/blob/main/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=true` and valid `AUTH0_KEYWORD_REPLACE_MAPPINGS` to activate preservation, enforced in [`src/context/index.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/context/index.ts).
- **Address-based preservation**: The `preserveKeywords` function in [`src/keywordPreservation.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/keywordPreservation.ts) builds 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`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/context/yaml/index.ts)) and Directory ([`src/context/directory/index.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/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`](https://github.com/auth0/auth0-deploy-cli/blob/main/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`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/context/yaml/index.ts) (lines 154‑155) and [`src/context/directory/index.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/context/directory/index.ts) (lines 92‑93), the flag passes through to the shared preservation logic in [`src/keywordPreservation.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/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.