248 lines
8.7 KiB
Plaintext
248 lines
8.7 KiB
Plaintext
export const metadata = {
|
|
title: `Caching Module Concepts`,
|
|
}
|
|
|
|
# {metadata.title}
|
|
|
|
In this guide, you'll learn about the main concepts of the [Caching Module](../page.mdx), including cache keys, cache tags, and automatic cache invalidation.
|
|
|
|
## Cache Keys
|
|
|
|
Cache keys uniquely identify cached data in the caching service. The Caching Module automatically generates cache keys when you cache data with Query or the Index Module.
|
|
|
|
### Custom Cache Keys
|
|
|
|
When you cache custom data with the Caching Module's service, you can generate a cache key using the [computeKey](/references/caching-service#computeKey) method. This method generates a unique key based on the data you want to cache.
|
|
|
|
For example:
|
|
|
|
```ts
|
|
const data = { id: "prod_123", title: "Product 123" }
|
|
const key = await cachingModuleService.computeKey(data)
|
|
await cachingModuleService.set({
|
|
key,
|
|
tags: ["Product:prod_123", "Product:list:*"],
|
|
data,
|
|
})
|
|
```
|
|
|
|
The `computeKey` method takes an object as input and generates a unique key based on its properties.
|
|
|
|
The generated key is a hash string that uniquely identifies the data. The has doesn't change based on the order of properties in the object.
|
|
|
|
For example, the following two objects generate the same cache key:
|
|
|
|
```ts
|
|
const key1 = await cachingModuleService.computeKey({ id: "prod_123", title: "Product 123" })
|
|
const key2 = await cachingModuleService.computeKey({ title: "Product 123", id: "prod_123" })
|
|
|
|
console.log(key1 === key2) // true
|
|
```
|
|
|
|
### When to Use Custom Cache Keys?
|
|
|
|
Use custom cache keys when you're caching custom data with the Caching Module's service. This ensures that the cached data is uniquely identified and can be retrieved or invalidated correctly.
|
|
|
|
You can also pass a custom key to Query or the Index Module when caching data. This is useful when you want to use the key for custom invalidation or retrieval.
|
|
|
|
Learn more about passing custom keys in the [Query guide](!docs!/learn/fundamentals/module-links/query#set-cache-key).
|
|
|
|
---
|
|
|
|
## Cache Tags
|
|
|
|
Cache tags are useful for grouping cached data, making it easier to invalidate or retrieve related cached entries.
|
|
|
|
When you cache data with the Query or Index Module, the Caching Module automatically generates cache tags based on the entity being queried and its retrieved relations.
|
|
|
|
When you cache custom data with the Caching Module's service, you can pass custom tags to the `set` and `get` methods.
|
|
|
|
### Caching Tags Convention
|
|
|
|
The Caching Module generates cache tags in the following format:
|
|
|
|
- `Entity:id`: Cache tag for a single record of an entity. For example, `Product:prod_123` for caching a single product with the ID `prod_123`.
|
|
- `Entity:list:*`: Cache tag for a list of records of an entity. For example, `Product:list:*` for caching a list of products.
|
|
|
|
<Note>
|
|
|
|
`Entity` is the pascal-cased name of the data model, which you pass as the first parameter to `model.define` when defining the model.
|
|
|
|
</Note>
|
|
|
|
When you use custom tags, ensure they adhere to the above convention. Otherwise, the Caching Module cannot automatically invalidate your cached data. You'll have to [invalidate](/references/caching-service#clear) the cached data manually.
|
|
|
|
For example:
|
|
|
|
```ts
|
|
const key = await cachingModuleService.computeKey(data)
|
|
await cachingModuleService.set({
|
|
key,
|
|
tags: ["Product:list:*", "Product:prod_123"],
|
|
data,
|
|
})
|
|
```
|
|
|
|
### When to Use Custom Tags?
|
|
|
|
Use custom tags when you want to group cached data for custom invalidation or retrieval.
|
|
|
|
Note that if your custom tags do not follow the [Caching Tags Convention](#caching-tags-convention), the Caching Module cannot automatically invalidate your cached data. You must manually [invalidate](/references/caching-service#clear) the cached data when it changes.
|
|
|
|
---
|
|
|
|
## Automatic Cache Invalidation
|
|
|
|
### When is Cache Automatically Invalidated?
|
|
|
|
The Caching Module automatically invalidates cached data when the underlying data changes through database operations such as create, update, or delete.
|
|
|
|
For example, if you cache a list of products with the tag `Product:list:*` and a new product is created, the Caching Module automatically invalidates the cached list of products.
|
|
|
|
This ensures that your application always serves fresh data and avoids serving stale or outdated information.
|
|
|
|
The following table shows when the Caching Module invalidates cached data based on different database operations:
|
|
|
|
<Table>
|
|
<Table.Header>
|
|
<Table.Row>
|
|
<Table.HeaderCell>
|
|
Database Operation
|
|
</Table.HeaderCell>
|
|
<Table.HeaderCell>
|
|
Invalidated Cache Tags
|
|
</Table.HeaderCell>
|
|
</Table.Row>
|
|
</Table.Header>
|
|
<Table.Body>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
Create
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
`Entity:list:*` (`Product:list:*`)
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
Update
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
`Entity:{id}`, `Entity:list:*` if the list includes the updated record. (`Product:prod_123`, `Product:list:*`)
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
Delete
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
`Entity:list:*` (`Product:list:*`)
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
</Table.Body>
|
|
</Table>
|
|
|
|
### Which Data is Automatically Invalidated?
|
|
|
|
The Caching Module automatically invalidates your cached data when:
|
|
|
|
1. The data includes an `id` field. This is used internally to map the data to the corresponding cache tags.
|
|
- When retrieving data with Query or the Index Module, ensure the `id` field is included in the `fields` option.
|
|
|
|
```ts
|
|
const { data: products } = useQueryGraphStep({
|
|
entity: "product",
|
|
fields: ["id", "title"], // Ensure 'id' is included, or pass '*'
|
|
options: {
|
|
cache: {
|
|
enable: true,
|
|
},
|
|
},
|
|
})
|
|
```
|
|
|
|
- When caching custom data with the Caching Module's service, ensure the data object includes an `id` property.
|
|
2. Custom tags follow the [Caching Tags Convention](#caching-tags-convention).
|
|
|
|
```ts
|
|
const data = { id: "prod_123", title: "Product 123" }
|
|
const key = await cachingModuleService.computeKey(data)
|
|
await cachingModuleService.set({
|
|
key,
|
|
tags: ["Product:prod_123", "Product:list:*"],
|
|
data,
|
|
})
|
|
```
|
|
|
|
3. The `autoInvalidate` option is not set or is set to `true`. This option is enabled by default.
|
|
|
|
```ts
|
|
const { data: products } = useQueryGraphStep({
|
|
entity: "product",
|
|
fields: ["id", "title"],
|
|
options: {
|
|
cache: {
|
|
enable: true,
|
|
// This is enabled by default
|
|
// autoInvalidate: true,
|
|
},
|
|
},
|
|
})
|
|
```
|
|
|
|
### Invalidation of Related Entities
|
|
|
|
If the cached data includes relations, and the relation is updated, the Caching Module also invalidates the cache tags for the related entity.
|
|
|
|
For example, consider the following Query usage:
|
|
|
|
```ts
|
|
const { data: products } = useQueryGraphStep({
|
|
entity: "product",
|
|
fields: ["id", "title", "variants.*"],
|
|
options: {
|
|
cache: {
|
|
enable: true,
|
|
},
|
|
},
|
|
})
|
|
```
|
|
|
|
If the product's variant is updated, the Caching Module invalidates the cache tags for both the `Product` and `ProductVariant` entities.
|
|
|
|
### When to Disable Automatic Invalidation?
|
|
|
|
Disabling automatic invalidation means the data remains in the cache until it expires (based on the TTL) or is manually invalidated.
|
|
|
|
Consider disabling automatic invalidation in the following cases:
|
|
|
|
1. You're caching data that rarely changes, such as a list of countries.
|
|
2. You want to manage cache invalidation manually, such as when caching data as part of a custom workflow where you want to control when the cache is invalidated.
|
|
3. You're caching data that does not belong to a Medusa data model, such as data from an external API or computed values. This data is not automatically invalidated by default.
|
|
|
|
Disable automatic invalidation by setting the `autoInvalidate` option to `false` when caching data with Query, the Index Module, or the Caching Module's service.
|
|
|
|
When you disable automatic invalidation, manually [invalidate](/references/caching-service#clear) the cached data when it changes.
|
|
|
|
---
|
|
|
|
## Caching Best Practices
|
|
|
|
### Cache Rarely-Changing Data
|
|
|
|
Cache data that is read frequently but changes infrequently, such as product information, categories, or static content.
|
|
|
|
Caching such data can significantly improve performance and reduce database load.
|
|
|
|
### Do Not Cache Dynamic Data
|
|
|
|
Avoid caching data that changes frequently or is user-specific, such as shopping cart contents, user sessions, or product pricing.
|
|
|
|
Caching such data can lead to inconsistencies and stale information being served to users. It also increases bandwidth and memory usage, as the cache is updated frequently.
|
|
|
|
### Do Not Cache Frequently Updated Data
|
|
|
|
Avoid caching data that is updated frequently, such as inventory levels or order statuses.
|
|
|
|
Caching such data increases the overhead of cache invalidation and may lead to performance degradation.
|