---
title: 'Caching queries in Prisma Postgres'
sidebar_label: 'Caching'
metaTitle: 'Caching queries in Prisma Postgres'
metaDescription: 'Learn about caching queries in Prisma Postgres'
tocDepth: 3
toc: true
---

Prisma Postgres supports built-in query caching to reduce database load and improve query performance. You can configure cache behavior using the `cacheStrategy` option available in all read queries.

This feature is powered by an internal caching layer enabled through [Prisma Accelerate](/accelerate), but you do not need to interact with Accelerate directly unless you're using your own database.

## Setting up caching in Prisma Postgres

To enable query caching in your Prisma Postgres project, you need to configure Accelerate caching and set up the client extension. Follow these steps:

### 1. Enable caching in the Platform Console

1. Go to the [Platform Console](https://console.prisma.io) and navigate to your project dashboard
2. In the "Connect to your database" section, click **Connect**
3. Toggle **Enable Accelerate caching** to activate the caching layer
4. Copy the generated connection string

Your connection string will look like this:

```env
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=ey...."
```

Replace the connection string in your `.env` file with this new Accelerate-enabled URL.

### 2. Install the Accelerate extension

Install the required client extension in your project:

```bash
npm install @prisma/extension-accelerate
```

### 3. Configure Prisma Client with caching

Update your Prisma Client setup to use the Accelerate extension:

<TabbedContent code>

<TabItem value="standard" label="Standard runtime">

```ts
import { PrismaClient } from '../generated/prisma/client'
import { withAccelerate } from '@prisma/extension-accelerate'

const prisma = new PrismaClient({
  accelerateUrl: process.env.DATABASE_URL,
}).$extends(withAccelerate())
```

</TabItem>

<TabItem value="edge" label="Edge runtime">

```ts
import { PrismaClient } from '@prisma/client/edge'
import { withAccelerate } from '@prisma/extension-accelerate'

const prisma = new PrismaClient({
  accelerateUrl: process.env.DATABASE_URL,
}).$extends(withAccelerate())
```

</TabItem>

</TabbedContent>

### 4. Start caching your queries

Once configured, you can add caching to any read query using the `cacheStrategy` option:

```ts
await prisma.user.findMany({
  cacheStrategy: {
    ttl: 60, // Cache for 60 seconds
  },
})
```

Your caching setup is now complete! Continue reading to learn about different cache strategies and how to optimize them for your use case.

## Cache strategies

For all read queries in Prisma Client, you can define the `cacheStrategy` parameter that configures cache behavior. The cache strategy allows you to define two main characteristics of the cache:

- **Time-to-live (TTL):** Duration in seconds a cached response is considered _fresh_.
- **Stale-while-Revalidating (SWR):** Duration in seconds a stale cache response is considered acceptable while the cache is refreshed in the background

## Time-to-live (TTL)

Time-to-Live (TTL) determines how long cached data is considered fresh. By specifying the `ttl` in seconds, you can control the duration for which data in the cache remains valid. When a read query is executed, if the cached response is within the `ttl` limit, Prisma Client retrieves the data from the cache without querying the database. If the cached data is not available or has expired, Prisma Client queries the database and stores the results in the cache for future requests.

Use `ttl` in `cacheStrategy` and specify the TTL of the query in seconds:

```javascript
await prisma.user.findMany({
  cacheStrategy: {
    //add-next-line
    ttl: 60,
  },
});
```

With a specified TTL of 60 seconds, the majority of requests will result in
a cache hit throughout the TTL duration:

![TTL](/img/accelerate/ttl.png)

TTL is useful for reducing database load and latency for data that does not require frequent updates.

### Invalidate the TTL and keep your cached query results up-to-date

If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `ttl` (Time-To-Live). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed.

For example, if a dashboard displays customer information and a customer’s contact details change, TTL (Time-To-Live) settings ensure the cache automatically expires after a set duration. This allows the system to refresh only the updated data at the next access, ensuring support staff always see the latest information without manually refreshing the cache.

However, in cases where immediate updates are required before the TTL expires, cache invalidation allows the system to proactively clear specific data from the cache. This forces a refresh of the updated information instantly, so support staff always have the most current details without waiting for the TTL to trigger.


To invalidate a cached query result, you can add tags and then use the `$accelerate.invalidate` API.

:::note

On-demand cache invalidation is available with our paid plans. For more details, please see our [pricing](https://www.prisma.io/pricing#accelerate).

:::

To invalidate the query below, you need to provide the cache tag in the `$accelerate.invalidate` API:

```ts
await prisma.user.findMany({
    cacheStrategy: {
      ttl: 60,
      //add-next-line
      tags: ["findMany_users"],
    },
});

// This is how you would invalidate the cached query above.
//add-start
await prisma.$accelerate.invalidate({
    tags: ["findMany_users"],
});
//add-end
```

## Stale-While-Revalidate (SWR)

Stale-While-Revalidate (SWR) allows you to control how long Prisma Postgres can serve stale cache data while fetching fresh data in the background. When a read query is executed, Prisma Postgres checks the age of the cached response against the `swr` duration. If the cache data is within the `swr` limit, Prisma Postgres serves the stale data while simultaneously refreshing the cache by fetching the latest data from the database.

Use `swr` in `cacheStrategy` and specify the SWR of the query in seconds:

```javascript
await prisma.user.findMany({
  cacheStrategy: {
    //add-next-line
    swr: 60,
  },
});
```

When specifying a SWR of 60 seconds, the cache serves stale data until the cache refreshes itself in the background after each request:

![SWR](/img/accelerate/swr.png)

### Invalidate the SWR and keep your cached query results up-to-date

If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `swr` (Stale-While-Revalidate). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed.

For example, consider a dashboard that displays stock levels for products in a warehouse. With SWR (Stale-While-Revalidate) settings, the dashboard can immediately display the last known stock data, even if it’s slightly outdated, while new data is fetched in the background. This ensures that staff can continue working with recent information without waiting, with the stock levels updating as soon as revalidation completes.

However, in cases where stock data needs to be updated immediately—for instance, if a product is low in stock and the count needs real-time accuracy—cache invalidation allows the system to proactively clear specific data from the cache. This forces a refresh of the latest stock data instantly, so staff always have the most up-to-date information without waiting for SWR to complete the revalidation.

To invalidate a cached query result, you can add tags and then use the `$accelerate.invalidate` API.

:::note

On-demand cache invalidation is available with our paid plans. For more details, please see our [pricing](https://www.prisma.io/pricing#accelerate).

:::

To invalidate the query below, you need to provide the cache tag in the `$accelerate.invalidate` API:

```ts
await prisma.user.findMany({
    cacheStrategy: {
      swr: 60,
      //add-next-line
      tags: ["findMany_users"],
    },
});

// This is how you would invalidate the cached query above.
//add-start
await prisma.$accelerate.invalidate({
    tags: ["findMany_users"],
});
//add-end
```

## Selecting a cache strategy

Caching helps you improve query response times and reduce database load. However, it also means you might serve stale data to the client. Whether or not serving stale data is acceptable and to what extent depends on your use case. `ttl` and `swr` are parameters you can use the tweak the cache behavior.

### Cache strategy using TTL

Use TTL to reduce database load when stale cached data is acceptable.

#### Use case: Product catalog in e-commerce applications

Consider an e-commerce application with a product catalog that doesn't frequently change. By setting a `ttl` of, let's say, 1 hour, Prisma Client can serve cached product data for subsequent user requests within that hour without hitting the database. This significantly reduces the database load and improves the response time for product listing pages.

**When to invalidate:** If there are critical updates to the catalog, such as a major price change or product availability adjustment, the [cache should be invalidated](/postgres/database/caching#on-demand-cache-invalidation) immediately to prevent customers from seeing outdated information.

### Cache strategy using SWR

Use SWR to respond quickly to requests with minimal stale data. While it does not reduce database load, it can improve response times significantly.

#### Use case: User profile in social media platforms

Imagine a social media platform where user profiles are frequently accessed. By leveraging `swr` with a duration of, let's say, 5 minutes, Prisma Postgres can serve the cached user profile information quickly, reducing the latency for profile pages. Meanwhile, in the background, it refreshes the cache after every request, ensuring that any updates made to the profile are eventually reflected for subsequent requests.

**When to invalidate:** If a user makes significant updates to their profile, such as changing their profile picture or bio, the cache should be [invalidated](/postgres/database/caching#on-demand-cache-invalidation) immediately to ensure that followers see the latest updates without waiting for the SWR refresh.

### Cache strategy using TTL + SWR

For very fast response times and reduced database load, use both TTL and SWR. You can use this strategy to fine-tune your application’s tolerance for stale data.

Use `ttl` and `swr` in `cacheStrategy` and specify the TTL and SWR of the query in seconds:

```javascript
await prisma.user.findMany({
  cacheStrategy: {
    //add-start
    ttl: 30,
    swr: 60,
    //add-end
  },
});
```

When specifying a TTL of 30 seconds and SWR of 60 seconds, the cache serves fresh data for the initial 30 seconds. Subsequently, it serves stale data until the cache refreshes itself in the background after each request:

![ttl_and_swr.png](/img/accelerate/ttl_and_swr.png)

#### Use case: News articles

Consider a news application where articles are frequently accessed but don't require real-time updates. By setting a `ttl` of 2 hours and an `swr` duration of 5 minutes, Prisma Client can serve cached articles quickly, reducing latency for readers. As long as the articles are within the `ttl`, users get fast responses. After the `ttl` expires, Prisma Client continues to serve the stale articles for up to an additional 5 minutes, revalidating the cache with the latest news from the database in response to a new query. This helps maintain a balance between performance and freshness.

**When to invalidate:** If a critical update or breaking news article is published, the cache should be [invalidated](/postgres/database/caching#on-demand-cache-invalidation) immediately to ensure readers see the latest information without delay. This approach is especially useful for applications where certain news items may need to override the normal cache cycle for timeliness.

## On-demand cache invalidation

If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `ttl` (Time-To-Live) or `swr` (Stale-While-Revalidate) [cache strategy](/postgres/database/caching#cache-strategies). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed.

You can invalidate the cache using the [`$accelerate.invalidate` API](/accelerate/api-reference#accelerateinvalidate):

:::note

To programmatically invalidate cached queries, a paid plan is required. See our [pricing for more details](https://www.prisma.io/pricing#accelerate).

:::

```ts
await prisma.user.findMany({
  where: {
    email: {
      contains: "alice@prisma.io",
    },
  },
  cacheStrategy: {
    swr: 60,
    ttl: 60,
    // highlight-start
    tags: ["emails_with_alice"],
    // highlight-end
  },
});
```

You need to provide the cache tag in the `$accelerate.invalidate` API:

```ts
try {
  // highlight-start
  await prisma.$accelerate.invalidate({
    tags: ["emails_with_alice"],
  });
  // highlight-end
} catch (e) {
  if (e instanceof Prisma.PrismaClientKnownRequestError) {
    // The .code property can be accessed in a type-safe manner
    if (e.code === "P6003") {
      console.log(
        "The cache invalidation rate limit has been reached. Please try again later."
      );
    }
  }
  throw e;
}
```

Explore the [demo app](https://pris.ly/test-cache-invalidation) to see how cached query results in Prisma Postgres are invalidated on demand, shown in a clear timeline.

## Default cache strategy

Prisma Postgres defaults to **no cache** to avoid unexpected issues. While caching can improve performance, incorrect usage may lead to errors.

For instance, if a query is executed on a critical path without specifying a cache strategy, the result may be incorrect, with no clear explanation. This issue often arises when implicit caching is unintentionally left enabled.

To avoid such problems, you must explicitly opt-in to caching. This ensures you are aware that caching is not enabled by default, preventing potential errors.

:::note

When no cache strategy is specified or during a cache miss, the cache layer routes all queries to the database through a connection pool instance near the database region.

:::