# Generating dynamic cache keys with variables

## Introduction

When an [add to cache shape](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/process-flow-shapes/advanced-shapes/cache/add-to-cache-shape) is dropped into a process flow, the entire incoming payload is cached and associated with the given **cache key**. Depending on the cache type, you can load this cache later in the same flow or in a different flow.&#x20;

In the simplest scenario, your given cache key would be a static value (e.g. `customers`) and you would use this to load the entire cache (containing perhaps tens, hundreds, even thousands of items) where required. But what if you want to load a specific item from a cache, rather than the whole thing?

This is where **dynamic cache keys** are so useful.&#x20;

## How it works

To load data from a cache, you configure a **load from cache** shape with the required `cache`  and a single `cache key`. All data associated with your given `cache key` is loaded.&#x20;

Consider the example incoming  payload below, where four records are cached with a static `cache key` with a value of `customers`:

{% code title="cache key: customers" lineNumbers="true" %}

```json
[
    {
        "id": 1000000001,
        "first_name": "Jane",
        "last_name": "Smith",
        "items": {
           "itemref": "0000001",
            "item1": "apples",
            "item2": "oranges",
            "item3": "pears"
        }
    },
    {
        "id": 1000000002,
        "first_name": "George",
        "last_name": "Jones",
        "items": {
           "itemref": "0000002",
            "item1": "tangerines",
            "item2": "peaches",
            "item3": "grapes"
        }
    },
    {
        "id": 1000000003,
        "first_name": "Bob",
        "last_name": "Brown",
        "items": {
           "itemref": "0000003",
            "item1": "nectarines",
            "item2": "raspberries",
            "item3": "strawberries"
        }
    },
    {
        "id": 1000000004,
        "first_name": "Marjorie",
        "last_name": "Simpson",
        "items": {
           "itemref": "0000004",
            "item1": "blueberries",
            "item2": "cranberries",
            "item3": "apricots"
        }
    }
]
```

{% endcode %}

If we were to configure a **load from cache** shape to access the `customers` cache key, all four records would be loaded.

So, in order to load specific items from a cache, the incoming data must be added to a cache in such a way that we can easily target individual items. We need an efficient way to take incoming data, batch it into single-record payloads and add each of these to the cache with its own unique, identifying **cache key** - i.e.:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td><p><strong>cache:</strong> customerData<br><strong>cache key:</strong> customer-1000000001</p><pre class="language-json"><code class="lang-json">[
    {
        "id": 1000000001,
        "first_name": "Jane",
        "last_name": "Smith",
        "items": {
           "itemref": "0000001",
            "item1": "apples",
            "item2": "oranges",
            "item3": "pears"
        }
    }
]
</code></pre></td><td></td><td></td></tr><tr><td><p><strong>cache:</strong> customerData<br><strong>cache key:</strong> customer-1000000002</p><pre class="language-json"><code class="lang-json">[
    {
        "id": 1000000002,
        "first_name": "George",
        "last_name": "Jones",
        "items": {
           "itemref": "0000002",
            "item1": "tangerines",
            "item2": "peaches",
            "item3": "grapes"
        }
    }
]
</code></pre></td><td></td><td></td></tr><tr><td><p><strong>cache:</strong> customerData<br><strong>cache key:</strong> customer-1000000003</p><pre class="language-json"><code class="lang-json">[
    {
        "id": 1000000003,
        "first_name": "Bob",
        "last_name": "Brown",
        "items": {
           "itemref": "0000003",
            "item1": "nectarines",
            "item2": "raspberries",
            "item3": "strawberries"
        }
    }
]
</code></pre></td><td></td><td></td></tr><tr><td><p><strong>cache:</strong> customerData<br><strong>cache key:</strong> customer-1000000004</p><pre class="language-json"><code class="lang-json">[
    {
        "id": 1000000004,
        "first_name": "Marjorie",
        "last_name": "Simpson",
        "items": {
           "itemref": "0000004",
            "item1": "blueberries",
            "item2": "cranberries",
            "item3": "apricots"
        }
    }
]
</code></pre></td><td></td><td></td></tr></tbody></table>

We can achieve this as follows:

<table><thead><tr><th>Action</th><th>Outcome</th><th data-hidden>#</th><th data-hidden>Outcome</th><th data-hidden>Outcome</th><th data-hidden>Outcome</th><th data-hidden>Step</th></tr></thead><tbody><tr><td>Place a <a href="../../../standard-shapes/flow-control-shape">flow control</a> shape immediately before the <strong>add to cache</strong> shape and configure it to create batches of 1 at the appropriate level for your data.</td><td>The incoming payload is batched into multiple payloads - one payload per data element (e.g. one order per payload, one customer per payload, one product per payload, etc.).</td><td>1</td><td>The subsequent <strong>add to cache</strong> shape receives multiple payloads, each containing a single record.</td><td>Incoming data is batched into single-record payloads and these are sent on to the subsequent <strong>add to cache</strong> shape.</td><td>The incoming payload is batched into multiple payloads - one payload per data element (e.g. one order per payload, one customer per payload, one product per payload, etc.). </td><td>1</td></tr><tr><td>Configure the <strong>add to cache</strong> shape and specify a <strong>payload variable</strong> as the <strong>cache key</strong>, where the variable looks for the first occurrence of a uniquely identifying element in the payload (typically an id or reference number).</td><td>The <strong>add to cache</strong> shape receives and caches single-record payloads from the flow control shape. The <strong>cache key</strong> for each payload is generated dynamically by resolving the <strong>payload variable</strong> from each incoming payload.</td><td>2</td><td>Each time a payload hits the <strong>add to cache</strong> shape, it gets added to the cache with its own cache key, resolved from the given payload variable. Now we can easily target single or multiple records to be loaded via a <strong>load from cache</strong> shape.</td><td>Multiple payloads are received from the <strong>flow control</strong> shape. Each one is added to the cache with its own cache key, resolved from the given payload variable. These cache keys <a href="../load-from-cache-shape/what-cached-data-do-you-want-to-load">can now be referenced by subsequent load from cache shapes</a>. Since each cache key contains a single record, we now have a way to target specific records from our original payload.</td><td>The <strong>add to cache</strong> shape receives and caches single-record payloads from the <strong>flow control</strong> shape - the <strong>cache key</strong> for each payload is generated dynamically by resolving the <strong>payload variable</strong> for each incoming payload.  </td><td>2</td></tr></tbody></table>

{% hint style="info" %}
[Flow control](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/process-flow-shapes/standard-shapes/flow-control-shape) is an easy way to batch incoming data into single-record payloads, however you may prefer an alternative approach. The important point is that the add to cache shape must receive single-record payloads - how you achieve this is up to you.
{% endhint %}

## Need to know

* When you specify a dynamic variable as the **cache key**, the value for that variable is injected into the key. To prevent the case where large amounts of data are passed into the key, there is a character limit is 128 characters.&#x20;
* Any combination of [payload](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/dynamic-variables/payload-variables), [flow](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/dynamic-variables/flow-variables) and [metadata](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/dynamic-variables/metadata-variables) variables can be used to form cache key names.
* When using dynamic variables for auto-generated cache keys, resolved variable values must not contain full stop (.) or colon (:) characters.

## Using a variable to generate dynamic cache keys&#x20;

Follow the steps below to configure an **add to cache** shape with a [payload variable](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/dynamic-variables/payload-variables) for generating dynamic cache keys.

{% hint style="info" %}
These steps assume that you have already defined a **flow control** shape (or some other means) to ensure that the **add to cache** shape receives single-record payloads.
{% endhint %}

**Step 1**\
[Drop an add to cache shape into your process flow](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/process-flow-shapes/advanced-shapes/cache/add-to-cache-shape/..#adding-an-add-to-cache-shape-to-a-process-flow), where required.

<details>

<summary><img src="https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2FuKTXJEY34CVnak6PxrOz%2Fexample%20icon%202.svg?alt=media&#x26;token=7c8af2c5-9519-4757-bea9-172569a023bd" alt="" data-size="line"> Example</summary>

In the example below, we have an incoming payload which includes orders in an `orders` array:

![](https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2Fdkp8nCNrIeJBDviHOiVf%2Fpayload%201.png?alt=media\&token=81022e8c-4710-4e27-b1de-6271250db0ba)

If we want to add these orders to a cache, we need to split them into batches of 1, so our **flow control** shape is configured as below:

![](https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2FLJozBKJs2zaajMb0cr97%2Fpayload%202.png?alt=media\&token=9c2669eb-945b-45b4-8fc3-d6e7b6e916d0)

This will generate two payloads. So, if we go on to drop an **add to cache** shape immediately after, each of these payloads will be cached (and therefore retrieved) separately.

</details>

**Step 2**\
In the **add to cache** shape settings, choose to **create cache**:

<div align="left"><figure><img src="https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2F6P8vLwNCn4zCJ2xCMH84%2Fcreate%20cache%201.png?alt=media&#x26;token=ac73e4af-ccbd-4f83-be5d-0d3fb6675181" alt="" width="375"><figcaption></figcaption></figure></div>

**Step 3**\
Set the **cache level** and **name** as required and save changes.

<div align="left"><figure><img src="https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2FfYyWN7q4USA3WchZjQB1%2Fcache%20variable%202.png?alt=media&#x26;token=e6995d09-dfde-4256-984d-ad3b3f4bdc01" alt="" width="375"><figcaption></figcaption></figure></div>

{% hint style="info" %}
For more information on these fields please see the [add to cache shape](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/process-flow-shapes/advanced-shapes/cache/add-to-cache-shape/..#adding-an-add-to-cache-shape-to-a-process-flow) page.
{% endhint %}

**Step 4**\
Select the cache that you just created - for example:

<div align="left"><figure><img src="https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2FsGZD7oI3Am0myXmcbMsP%2Fcache%20variable%203.png?alt=media&#x26;token=f68b1310-7829-4277-b56a-6e94f9263d8f" alt="" width="349"><figcaption></figcaption></figure></div>

**Step 5**\
Move down to the **cache key** field and enter the required key. Here, you use standard [payload variable syntax ](https://doc.wearepatchworks.com/product-documentation/process-flows/dynamic-variables/payload-variables#payload-variable-syntax)to define your target data element:

{% code lineNumbers="true" %}

```
[[payload.<schema notation>]]
```

{% endcode %}

...where `schema notation` should be replaced with the notation path to the first occurrence of the required element in the payload which should be used to form the cache key. If required, you can also include a static prefix or suffix. For example:

{% code lineNumbers="true" %}

```
customer-[[payload.0.id>]]
```

{% endcode %}

The output of the payload variable will be used as the **cache key**.&#x20;

<details>

<summary><img src="https://2440044887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLYNcUBVQwSkOMG6KjZfz%2Fuploads%2FuKTXJEY34CVnak6PxrOz%2Fexample%20icon%202.svg?alt=media&#x26;token=7c8af2c5-9519-4757-bea9-172569a023bd" alt="" data-size="line"> Example</summary>

Consider the payload below:

{% code lineNumbers="true" %}

```json
{
  "orders": [
    {
      "id": 1,
      "customer": {
        "email": "joe.bloggs@wearepatchworks.com"
      }
    }
  ]
}
```

{% endcode %}

...and **our cache key** is specified as:

{% code lineNumbers="true" %}

```
customer-[[payload.0.id>]]
```

{% endcode %}

The generated **cache key** would be:

{% code lineNumbers="true" %}

```
customer-1
```

{% endcode %}

...where `1` is the id associated with the first object in the `orders` array.The&#x20;

</details>

{% hint style="info" %}
Our example uses dynamic payload variables however, you can also use metadata variables and/or flow variables. For more information please see [dynamics variables](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/dynamic-variables) section.&#x20;
{% endhint %}

{% hint style="warning" %}
When using dynamic variables for auto-generated cache keys, ensure that resolved variable values do not contain full stop (.) or colon (:) characters. For example:

&#x20;`[[payload.id]]` resolving to `1234567` is good\
&#x20;`[[payload.id]]` resolving to `123.4567` is bad&#x20;
{% endhint %}

**Step 6**\
Save the **add to cache** shape settings.

## Loading data from a cache

Cached data can be loaded via our load from cache shape. Please refer to the [Load from cache shape](https://doc.wearepatchworks.com/product-documentation/process-flows/building-process-flows/process-flow-shapes/advanced-shapes/cache/load-from-cache-shape) section for more information. &#x20;
