---
schema_version: "1"
id: 23d8a55f8450f7264214ced5b0f9c10ccdd8e30a3c30c4211b98d220e7c49548
title: eCDN Cache Rules
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/commerce-api/guides/cdn-cache-rules.md
canonical_url: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/cdn-cache-rules.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: cbd317721252d654543c270d171eccac45aad8395d65c1b9ea6b864f214b6c11
products:
  - Composable Storefront
  - Salesforce APIs
---
# eCDN Cache Rules

Cache rules allow you to control which content is eligible for caching at the eCDN. By default, eCDN only caches based on file extension and does not cache HTML pages or JSON responses. Cache rules enable you to make these previously uncacheable resources eligible for edge caching, which is a prerequisite for using cache purging by tags or paths.

Cache rules make content _eligible_ for caching, but do not force caching. Your origin server must send appropriate `Cache-Control` headers for content to actually be cached. When a cache rule matches a request, eCDN evaluates specific conditions to determine whether to cache the resource.

eCDN does **not** cache the resource if a cache rule matches and **any** of the following conditions are true:

- The `Cache-Control` header is set to `private`, `no-store`, `no-cache`, or `max-age=0`.
- No `Cache-Control` header is present.
- The `Set-Cookie` header exists.
- The HTTP request method is anything other than `GET`.

eCDN **does** cache the resource if a cache rule matches and **all** of the following conditions are true:

- The request method is `GET`.
- No Set-Cookie header is present.
- Either the `Cache-Control` header is set to `public` and `max-age` is greater than 0, or the `Expires` header is set to a future date.
  - If both `max-age` and an `Expires` header are set, `max-age` takes precedence.
  - If `s-maxage` is present, it takes precedence over `max-age`.

For more resources on caching in general, refer to the following resources:

- [Content Cache](https://developer.salesforce.com/docs/commerce/b2c-commerce/guide/b2c-content-cache.html)
- [SCAPI Caching](https://developer.salesforce.com/docs/commerce/commerce-api/guide/server-side-web-tier-caching.html)
- [Cache-Control HTTP Header](https://developer.salesforce.com/docs/commerce/commerce-api/guide/server-side-web-tier-caching.html#cache-control-http-header)

## Default Cached File Extensions

eCDN caches content based on file extension (not MIME type).

By default, eCDN caches the following file extensions:

Supported formats:

- 7Z, AVI, AVIF, APK, BIN, BMP, BZ2
- CLASS, CSS, CSV, DOC, DOCX, DMG
- EJS, EOT, EPS, EXE, FLAC, GIF, GZ
- ICO, ISO, JAR, JPG, JPEG, JS
- MID, MIDI, MKV, MP3, MP4, OGG, OTF
- PDF, PICT, PLS, PNG, PPT, PPTX, PS, RAR
- SVG, SVGZ, SWF, TAR, TIF, TIFF, TTF
- WEBM, WEBP, WOFF, WOFF2
- XLS, XLSX, ZIP, ZST

If your content has an extension that is not in the preceding list, use cache rules to make it eligible for caching. eCDN does not cache HTML, JSON, XML, or TXT files, except robots.txt.

The maximum cacheable file size is 5 GB.

## Cache Rule Parameters

### Required Parameters

| Parameter     | Type   | Description                                                                                                                                                                |
| ------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `description` | string | A description of the cache rule.                                                                                                                                           |
| `expression`  | string | A rule expression that defines when to apply the rule. Must use supported fields as described in the Supported Expression Fields section. Maximum length: 4096 characters. |
| `action`      | string | The action to perform. Currently, only `cache` is supported.                                                                                                               |

### Optional Parameters

| Parameter                 | Type             | Default                             | Description                                                                                                                                                                                                                                                     |
| ------------------------- | ---------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`                 | boolean          | `true`                              | Whether the rule is enabled.                                                                                                                                                                                                                                    |
| `excludeQueryStrings`     | array of strings | `null` (all query strings included) | List of query string parameters to **exclude** from the cache key. If provided, must be non-empty. Use empty array `[]` in PATCH to clear existing exclusions.                                                                                                  |
| `ignoreQueryStringsOrder` | boolean          | `false`                             | If `true`, query strings are sorted alphabetically before creating the cache key. This means `?a=1&b=2` and `?b=2&a=1` share the same cache entry.                                                                                                              |
| `respectStrongEtags`      | boolean          | `false`                             | If `true`, eCDN uses strong ETag header validation to ensure that resources in the cache and on the origin server are byte-for-byte identical.                                                                                                                  |
| `position`                | object           | Last position                       | Specifies where to insert the rule in the ruleset. Must specify either `before` or `after` with a rule ID. Cache rules are evaluated in the order they appear in the ruleset. Multiple cache rules can match the same request, and the last matching rule wins. |

## Supported Expression Fields for Cache Rules

Cache rule expressions use the same operators and functions as rate limiting rules and custom rules, and support a different set of fields. See [Comparison Operators](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/cdn-rule-expression-fields.md#comparison-operators), [Logical Operators](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/cdn-rule-expression-fields.md#logical-operators), and [Functions](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/cdn-rule-expression-fields.md#functions).

Cache rule expressions support the following fields:

| Field                  | Description                                                                                                                                                    | Usage in Expression               | Type                | Example                                                                                                                                    |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| **URI Full**           | Represents the full URI as received by the web server.                                                                                                         | `http.request.full_uri`           | String              | `http.request.full_uri eq "https://www.example.com/path/index?section=123456&expand=comments"`                                             |
| **URI**                | Represents the URI path and query string of the request.                                                                                                       | `http.request.uri`                | String              | `http.request.uri eq "/path/index?section=123456&expand=comments"`                                                                         |
| **URI Path**           | Represents the URI path of the request.                                                                                                                        | `http.request.uri.path`           | String              | `http.request.uri.path eq "/path/index"`                                                                                                   |
| **URI Query String**   | Represents the entire query string, without the `?` delimiter.                                                                                                 | `http.request.uri.query`          | String              | `http.request.uri.query eq "section=123456&expand=comments"`                                                                               |
| **URI Path Extension** | The lowercased file extension in the URI path without the dot (`.`) character.                                                                                 | `http.request.uri.path.extension` | String              | `http.request.uri.path.extension eq "html"`                                                                                                |
| **Host Name**          | Represents the host name used in the full request URI.                                                                                                         | `http.host`                       | String              | `http.host eq "www.example.com"`                                                                                                           |
| **Cookie**             | Represents the entire cookie as a string.                                                                                                                      | `http.cookie`                     | String              | `http.cookie eq "session=8521F670545D7865F79C3D7BEDC29CCE;-background=light"`                                                              |
| **Request Cookies**    | The `Cookie` HTTP header associated with a request represented as a Map (associative array).                                                                   | `http.request.cookies`            | `Map<String>\Array` | `any(http.request.cookies["app"][*] eq "test")`                                                                                            |
| **HTTP Headers**       | Represents HTTP request headers as a Map (or associative array).                                                                                               | `http.request.headers`            | `Map<String>\Array` | `any(http.request.headers["content-type"][*] eq "application/json")`                                                                       |
| **HTTP Referer**       | Represents the HTTP Referer request header, which contains the address of the web page that linked to the currently requested page.                            | `http.referer`                    | String              | `http.referer contains "www.example.com"`                                                                                                  |
| **User Agent**         | Represents the HTTP user agent, a request header that contains a characteristic string to allow identification of the client operating system and web browser. | `http.user_agent`                 | String              | `http.user_agent eq "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Safari/537.36"` |
| **X-Forwarded-For**    | The full value of the `X-Forwarded-For` HTTP header.                                                                                                           | `http.x_forwarded_for`            | String              | `http.x_forwarded_for eq "203.0.113.195, 70.41.3.18"`                                                                                      |
| **SSL/HTTPS**          | Returns true when the HTTP connection to the client is encrypted.                                                                                              | `ssl`                             | Boolean             | `ssl`                                                                                                                                      |

### Expression Examples

Match specific path pattern using regex:

```text
(http.request.uri.path matches ".*/product/[^/]+/?$")
```

Match on file extension type:

```text
(http.request.uri.path.extension eq "html")
```

Combine conditions:

```text
(http.request.uri.path matches ".*/product/[^/]+/?$" and http.request.uri.path.extension eq "html")
```

Explicitly exclude certain paths:

````text
(http.request.uri.path.extension eq "html" and not (http.request.uri.path contains "/checkout" or http.request.uri.path contains "/account"))
```sh

## API Usage

### Create a Cache Rule

This endpoint creates a cache rule in the specified zone.

**important:** A maximum of 200 cache rules is allowed in a single zone.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/cache/rules" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data '{
    "description": "Cache product detail pages",
    "expression": "(http.request.uri.path matches \".*/product/[^/]+/?$\" and http.request.uri.path.extension eq \"html\")",
    "action": "cache",
    "excludeQueryStrings": ["gclid", "utm_campaign"],
    "ignoreQueryStringsOrder": true,
    "respectStrongEtags": true,
    "enabled": true
}'
````

Sample success response: 201 HttpStatus code response body contains the cache rule that was created.

````json
{
  "data": [
    {
      "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
      "description": "Cache product detail pages",
      "expression": "(http.request.uri.path matches \".*/product/[^/]+/?$\" and http.request.uri.path.extension eq \"html\")",
      "action": "cache",
      "excludeQueryStrings": ["gclid", "utm_campaign"],
      "ignoreQueryStringsOrder": true,
      "respectStrongEtags": true,
      "enabled": true,
      "lastUpdated": "2022-12-14T21:25:22.329194Z"
    }
  ]
}
```sh

### Get All Cache Rules

This endpoint returns all of the cache rules in the specified zone in order of priority. If no cache rules exist, an empty array `[]` is returned (not 404).

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/cache/rules" \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json'
````

Sample success response: 200 HttpStatus code response body contains all of the cache rules in the specified zone.

```json
{
  "data": [
    {
      "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
      "description": "Cache product detail pages",
      "expression": "(http.request.uri.path matches \".*/product/[^/]+/?$\" and http.request.uri.path.extension eq \"html\")",
      "action": "cache",
      "excludeQueryStrings": ["gclid", "utm_campaign"],
      "ignoreQueryStringsOrder": true,
      "respectStrongEtags": true,
      "enabled": true,
      "lastUpdated": "2022-12-14T21:25:22.329194Z"
    },
    {
      "ruleId": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
      "description": "Cache category pages",
      "expression": "(http.request.uri.path matches \".*/category/[^/]+/?$\" and http.request.uri.path.extension eq \"html\")",
      "action": "cache",
      "ignoreQueryStringsOrder": false,
      "respectStrongEtags": false,
      "enabled": true,
      "lastUpdated": "2022-12-14T21:47:24.323223Z"
    }
  ]
}
```

**note:** `excludeQueryStrings` is only included in the response when query strings are explicitly excluded. If all query strings are included in the cache key, this field is omitted from the response.

### Update a Cache Rule

This endpoint updates the requested cache rule. If the requested rule does not exist, a 404 Not Found response is returned.

- You must provide at least one cache rule parameter in the request body.
- In the scenario where you have set `excludeQueryStrings` but wish to remove it (and thus have all query strings included in the cache key), you must include `"excludeQueryStrings": []` in the request body to clear the value.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/cache/rules/2c0fc9fa937b11eaa1b71c4d701ab86e" \
--request 'PATCH' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data '{
    "description": "Cache product detail pages - updated",
    "excludeQueryStrings": ["gclid", "utm_campaign", "ref", "source"],
    "enabled": false
}'
```

Sample success response: 200 HttpStatus code response body contains the requested cache rule.

````json
{
  "data": [
    {
      "ruleId": "2c0fc9fa937b11eaa1b71c4d701ab86e",
      "description": "Cache product detail pages - updated",
      "expression": "(http.request.uri.path matches \".*/product/[^/]+/?$\" and http.request.uri.path.extension eq \"html\")",
      "action": "cache",
      "excludeQueryStrings": ["gclid", "utm_campaign", "ref", "source"],
      "ignoreQueryStringsOrder": true,
      "respectStrongEtags": true,
      "enabled": false,
      "lastUpdated": "2022-12-14T22:30:15.123456Z"
    }
  ]
}
```sh

### Delete a Cache Rule

This endpoint deletes the requested cache rule. If the requested rule doesn't exist, a 404 Not Found response is returned.

```sh
curl "https://$CODE.api.commercecloud.salesforce.com/cdn/zones/v1/organizations/$ORG/zones/$ZONE/cache/rules/2c0fc9fa937b11eaa1b71c4d701ab86e" \
--request 'DELETE' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json'
````

Sample success response: 204 HttpStatus Code (No Content)

**note:** Deleting a rule doesn't purge cached content. Use the cache purge API if you need to immediately invalidate cached content.

## Best Practices and Common Mistakes

### Best Practices

1. Understand origin cache headers. Cache rules make content eligible, but origin must send the appropriate `Cache-Control` headers.
2. Start with specific rules. Begin with expressions scopes to specific pages and gradually expand.
3. Test in lower environments first. Always test cache rules in a development or staging environment before applying to production.
4. Use cache tags. Set `Cache-Tag` headers from origin to enable tag-based purging.
5. Exclude specific query strings. Use `excludeQueryStrings` to prevent cache fragmentation from tracking parameters and increase cache hit ratios.
6. Monitor cache hit ratios using BM Analytics or Logpush. Use the **Analytics** tab in Business Manager to monitor cache performance by viewing cache statuses. Alternatively, use [eCDN Logpush](https://developer.salesforce.com/docs/commerce/commerce-api/guide/cdn-zones-logpush.html) to monitor logs and view cache statuses, response times, and more.

### Common Mistakes

1. Caching authentication endpoints or personalized content. Avoid caching paths like `/login`, `/account`, `/cart`, etc. that contain user-specific data. Ensure origin sends the correct headers `private`, `no-store`, `no-cache`, or `max-age=0` or explicitly exclude the paths from any cache rules.
2. Overly broad expressions. Avoid expressions that are too broad and match all traffic. Use specific path patterns instead.
3. Assuming content will be cached. Cache rules make content eligible, but content is only cached if:
   1. Origin sends `Cache-Control: public, max-age=X` (where X \> 0\).
   2. No `Set-Cookie` header is present.
   3. Request method is `GET`.
4. After enabling caching, eligible requests are served from eCDN cache. Keep in mind when monitoring system statistics that these requests won't reach the origin.

## Common Use Cases

### Cache PWA Kit Product Detail Pages

PWA Kit serves server-side rendered HTML product pages that aren't cached by default. Create a cache rule to make product pages eligible for caching. For more information about improving performance for PWA Kit storefronts, see [Maximize Your Cache Hit Ratio](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/maximizing-your-cache-hit-ratio.html).

Sample cache rule:

```json
{
  "description": "Cache product detail pages",
  "expression": "(http.request.uri.path matches \".*/product/[^/]+/?$\" and http.request.uri.path.extension eq \"html\")",
  "action": "cache",
  "excludeQueryStrings": ["gclid", "utm_campaign"],
  "ignoreQueryStringsOrder": true,
  "respectStrongEtags": true,
  "enabled": true
}
```

### Cache SFRA Content Pages

SFRA content asset pages, landing pages, and marketing pages are HTML that you can cache.

Sample cache rule:

```json
{
  "description": "Cache SFRA content and marketing pages",
  "expression": "((http.request.uri.path contains \"/content/\" or http.request.uri.path contains \"/campaigns/\") and http.request.uri.path.extension eq \"html\")",
  "action": "cache",
  "ignoreQueryStringsOrder": true,
  "enabled": true
}
```

## Integrate with Cache Purge

Cache rules make content eligible for selective cache purging using the existing cache purge API. After creating cache rules, you can purge cached content by path or by tag. For details, see [cachePurge](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=cachePurge).

Use the [B2C CLI](https://developer.salesforce.com/docs/commerce/b2c-commerce/guides/b2c-developer-tooling.md):

```bash
# Required scopes: sfcc.cdn-zones, sfcc.cdn-zones.rw
export SFCC_CLIENT_ID='your-account-manager-client-id'
export SFCC_CLIENT_SECRET='your-account-manager-client-secret'
export SFCC_SHORTCODE='your-short-code'

npx @salesforce/b2c-cli ecdn cache purge \
  --tenant-id abcd_stg --zone stg-abcd-example-com.cc-ecdn.net \
  --path www.example.com/dw/shop/v25_10/products/12345
```

Purge by path:

```json
POST /{organizationId}/zones/{zoneId}/cachepurge
{
  "path": "www.example.com/dw/shop/v25_10/products/12345"
}
```

Purge by tag:

Set `Cache-Tag` headers from your origin, then purge by tag.

Origin response headers:

```text
Cache-Control: public, max-age=300
Cache-Tag: product-12345, category-shoes, page-product-detail
```

Purge request:

```json
POST /{organizationId}/zones/{zoneId}/cachepurge
{
  "tags": ["product-12345"]
}
```

## Frequently Asked Questions (FAQ)

### Can I use cache rules to bypass cache?

CDN-API cache rules currently only support making content eligible for caching (`action: "cache"`). As a workaround, ensure your origin sends `Cache-Control: private`, `no-store`, `no-cache`, or `max-age=0` for content that should not be cached. eCDN respects these headers and does not cache the content.

### What happens if multiple cache rules match?

All matching rules are evaluated, and **the last matching rule's settings take precedence**.

### Do cache rules override origin Cache-Control headers?

No, cache rules respect origin `Cache-Control` headers.

### Can I cache POST requests?

No. eCDN only caches GET requests, regardless of cache rule configuration. Cache rules can match POST/PUT/DELETE requests, but those requests won't be cached. You don't need to filter by HTTP method in your expression because eCDN automatically only caches GET requests.

### Why is my content not being cached?

If you created a cache rule but content still hits the origin:

1. Check origin headers. Verify origin sends `Cache-Control: public, max-age=X` (where X \> 0\).
2. Check for Set-Cookie. Responses with `Set-Cookie` headers are not cached.
3. Verify request method. eCDN only caches GET requests.
4. Verify rule expression. Ensure expression matches your URL patterns.
5. Check rule is enabled. Verify `enabled: true` in rule response.
6. Check the response headers. Look for `Cf-Cache-Status: HIT` (cached) or `MISS/DYNAMIC` (not cached).

### What should I do if stale content is being served?

1. Check cache TTL. Reduce `max-age` in origin `Cache-Control` header.
2. Purge cache. Use cache purge API after content updates.
3. Verify query strings. Ensure query parameters that affect content aren't excluded.

### What's the difference between `excludeQueryStrings` and `ignoreQueryStringsOrder`?

`excludeQueryStrings` removes specific query parameters from the cache key. `ignoreQueryStringsOrder` sorts query parameters alphabetically before creating the cache key. You can use them together to normalize URLs with tracking parameters.

### What happens if I delete a cache rule?

The rule is removed from the ruleset immediately. Previously cached content remains cached until:

- TTL expires (based on origin `Cache-Control: max-age`).
- Cache is purged manually via cache purge API.
- Origin sends updated `Cache-Control` headers.

Deleting a rule doesn't purge cached content. Use the [cachePurge API](https://developer.salesforce.com/docs/commerce/commerce-api/references/zones?meta=cachePurge) if you need to immediately invalidate cached content.
