How stories are cached in the Content Delivery API
Understanding and optimizing the caching system in Storyblok is crucial to reduce the number of API requests and deliver content faster to your users.
It also has a critical impact on the rate limit, see more info about this in our official documentation.
How caching works in Storyblok
Each space has a version
parameter, which is a Unix timestamp that is updated every time you publish new content. Thus, the parameter always reflects the most recent update to the public version of the space.
You can see the latest version
value for your space by making an API call to the spaces endpoint.
The stories endpoint also exposes the version, which is called cv
(cache version) and by default is equal to the version
parameter of the spaces endpoint.
The cv
is also a query parameter that is used to retrieve the stories. If it's not present in the API request, the Storyblok backend performs an HTTP redirect to the same endpoint with the latest available cv
value added to the URL.
Finally, the response to this call is cached in Storyblok's CDN, which means that any new call with the cv
parameter equal to the latest available will immediately serve the content from the cache without affecting the API request count.
That's why it's critical to retrieve the version
value and use it as the cv
query parameter in any subsequent API calls to the stories endpoint. This maximizes the cache usage, speeds up the response time, and significantly reduces the number of API calls that count against Storyblok's rate limit.
The most efficient way to get the version
number is to call the /spaces/me/
endpoint.
When a new story is published, the version
value is updated, but the previous value is still cached in the CDN. To get the latest content, you will need to use a cv
value that is up to date with the latest version.
Fetching, storing, and invalidating the cv
parameter used for API calls should be part of your application architecture. You can use cron jobs, custom events, or Storyblok's webhooks to know when to invalidate your stored cv
and retrieve a new one.
Storyblok SDKs and official JS client
If you use a JavaScript framework to interact with Storyblok, you will most likely want to use one of our official SDKs.
They are based on the JS client, designed to handle the cv
parameter in a way that, by default, helps you keep the number of API calls to a minimum. To get fresh content on your site as soon as you publish it, it's important that you understand how version caching works in the JS client, especially in the context of a server-side rendered (SSR) application or a long-running process.
How the JS client uses the cv
param
When you start your JavaScript application, a new instance of the JS client is created. When you make your first API call to the /stories/
endpoint, the JS client takes the version
number in the response and stores it in memory.
This way, it will reuse that value for all subsequent calls unless you provide a custom cv
parameter that overrides its cached value.
If you now make a call to the same endpoint without providing the cv
value, the cached value will be used.
If you never pass a custom cv
parameter, the behavior is the same as described above for HTTP calls: behind the scenes, a redirect is performed with the most recent cv
value, and the JS client stores that value.
This also happens in the SDKs. In the React SDK, for example, this is equivalent to the code we suggest in our documentation and playgrounds.
That's why if your application fetches a story without passing the cv
, the version of that story and any other story fetched after that call will be the same as the first call for the entire lifetime of the JS client in memory.
In the case of some server-rendered applications (like Next.js) the lifetime of the JS client instance may be longer than you expect, and may actually persist until you restart the server. That's why it's important to use webhooks or custom logic to revalidate the cache.
How to clear the JS client's cache
The easiest way to clear the JS client's cache is to call the flushCache()
method, which flushes the client's in-memory cache.
Another method that actually clears the cache is to call the /stories/
endpoint with the version: 'draft'
parameter. Getting the draft content will effectively flush the client cache, although this is only for preview or development environments.
How to always get fresh, uncached content
If you don't want to manage the version number, and want always to fetch the most recent content, simply passing a cv
parameter equal to the current time will effectively get fresh and uncached content.
This will "bypass" the CDN cache and always hit the Storyblok backend, because the requested version
will always be newer than the space latest version. This also means that any call made with this cv
value will count against our API rate limit, exactly as a raw call to the endpoint GET /cdn/stories?token=[YOUR_TOKEN]
To summarize
The key aspects of Storyblok's caching system include:
- Version Control
- Each content update generates a new version timestamp
- The version is exposed as
cv
(cache version) in API responses - Get the latest version via
/spaces/me
endpoint
- Cache Optimization
- CDN caching reduces API calls and improves performance
- Include
cv
parameter in requests to maximize cache usage - Automatic redirects add the latest version if
cv
is missing
- Implementation Strategy
- JS client automatically handles version caching
- In server-side rendered applications, store your own
version
somewhere and use webhooks or cron jobs to revalidate it to avoid the risk of outdated content - Use the current timestamp as
cv
to bypass caching when fresh content is needed and API count is not an issue