# Managing cache in your CARTO applications

The CARTO platform provides a cache layer to optimize performance and save precious computing resources from your cloud data warehouse. Understanding how caching works and the default settings for the different data sources ensures that users can manage data freshness effectively while balancing performance and cost considerations.

In this guide, you will learn:

* [Cache defaults: How cache works in CARTO](#cache-defaults-how-does-cache-work-in-carto)
* [How to adjust the cache layer](#how-to-adjust-cache)
* [How to completely invalidate some or all cached results](#completely-invalidate-cache)

## Cache defaults: How does cache work in CARTO

By default, CARTO stores the result of all queries to your data warehouse in a CARTO-managed CDN-based cache (for SaaS deployments) or in your `varnish-cache` (for Self-hosted deployments), ensuring that repeated requests for the same information do not require re-fetching data from your connection. This significantly improves performance and reduces data processing costs while maintaining data consistency based on predefined cache expiration times.

The duration of the cache (the time it takes for the cached result to expire) depends on the type of data source. Below is an explanation of the default cache behavior for the different features in CARTO.

### Visualizing tiles in a map (Maps API via deck.gl)

| Data Warehouse | Source Type | Default Duration (TTL)                                                |
| -------------- | ----------- | --------------------------------------------------------------------- |
| **BigQuery**   | Tables      | Indefinitely until the table is modified, with a minimum of 5 minutes |
|                | Queries     | 1 year                                                                |
|                | Tilesets    | 1 year or until the tileset is modified                               |
| **Snowflake**  | Tables      | Indefinitely until the table is modified, with a minimum of 5 minutes |
|                | Queries     | 1 year                                                                |
|                | Tilesets    | 1 year or until the tileset is modified                               |
| **Redshift**   | Tables      | 30 minutes                                                            |
|                | Queries     | 1 year                                                                |
|                | Tilesets    | 1 year                                                                |
| **Databricks** | Tables      | 30 minutes                                                            |
|                | Queries     | 1 year                                                                |
|                | Tilesets    | 1 year                                                                |
| **PostgreSQL** | Tables      | 30 minutes                                                            |
|                | Queries     | 1 year                                                                |
|                | Tilesets    | 1 year                                                                |
| **Oracle**     | Tables      | Indefinitely until the table is modified, with a minimum of 5 minutes |
|                | Queries     | 1 year                                                                |
|                | Tilesets    | 1 year or until the tileset is modified                               |

### Widgets and Requests to SQL API

| Data Warehouse          | Source Type     | Default Duration (TTL) |
| ----------------------- | --------------- | ---------------------- |
| **All Data Warehouses** | Models          | 5 minutes              |
|                         | SQL API Queries | 1 year                 |

## How to adjust the cache layer

In some circumstances, you may want to define specific freshness intervals for the data to ensure users in your application always work with the most up-to-date information.

{% hint style="info" %}
**Shorter cache duration may increase costs and decrease performance**

When you invalidate cached results or set short cache duration times, your application will require more SQL queries to be re-executed against your data warehouse. This will result in more data processing in the data warehouse, potentially leading to higher costs.

We recommend leaving the cache settings in their default settings, or adjusting them aiming for an optimal balance between data freshness and performance.
{% endhint %}

Generally speaking, adjusting cache settings is done by passing a [cache-control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) **HTTP header** with a `max-age` directive in all HTTP requests sent to the CARTO APIs. The `max-age` directive will control the duration in seconds (TTL) for the cached response.

Depending on the specific feature, the implementation of the `max-age` directive will be different. Below is a collection that details how to add it through the different features in CARTO for Developers.

### **CARTO + deck.gl: layers and widgets**

Use the [`headers`](https://deck.gl/docs/api-reference/geo-layers/mvt-layer#loadoptions) parameter directly in the [@deck.gl/CARTO sources](https://deck.gl/docs/api-reference/carto/overview#carto-layers) in your application to adjust cache settings.

**Example:**

{% code overflow="wrap" %}

```javascript
import { Deck } from '@deck.gl/core';
import { VectorTileLayer } from '@deck.gl/carto';
import { vectorQuerySource } from 'carto-api-client';

const data = vectorQuerySource({
  accessToken: 'XXX',
  connectionName: 'carto_dw',
  sqlQuery: 'SELECT * FROM cartobq.testtables.points_10k',
  headers: { 'cache-control': 'max-age=60' }
  // widgets and layers using this source will be cached for 60 seconds
});

const layer = new VectorTileLayer({
  data,
  pointRadiusMinPixels: 2,
  getLineColor: [0, 0, 0, 200],
  getFillColor: [238, 77, 90],
  lineWidthMinPixels: 1,
  // cache options in the source affect this layer's tiles
});

const result = await data.widgetSource.getFormula({
  column: 'store_name',
  operation: 'count'
  // cache options in the source affect the widget results
});

// etc..

```

{% endcode %}

### **Direct SQL API calls**

Specify a `cache-control` header in your HTTP requests to define the cache duration.

```bash
curl --location 'https://gcp-us-east1.api.carto.com/v3/sql/carto_dw/query?q=select%20*%20from%20carto-demo-data.demo_tables.airports' \
--header 'Authorization: Bearer ' \
--header 'Cache-Control: 'max-age=300'
```

You can learn more in our [**API Docs**](https://api-docs.carto.com/#3f1407e6-8c40-43c3-a8f8-21ae7d3618b6).

## How to completely invalidate some or all cached results

There are two methods to completely invalidate some or all cached results in your application.

### **Method 1: Using the `no-cache` directive**

To completely invalidate cache, a `no-cache` directive can be passed alongside `max-age=0` to instruct CARTO to completely invalidate the cache.

#### **CARTO + deck.gl: Layers and Widgets**

```javascript
import { Deck } from '@deck.gl/core';
import { VectorTileLayer } from '@deck.gl/carto';
import { vectorQuerySource } from 'carto-api-client';

const data = vectorQuerySource({
  accessToken: 'XXX',
  connectionName: 'carto_dw',
  sqlQuery: 'SELECT * FROM cartobq.testtables.points_10k',
  headers: { 'cache-control': 'no-cache, max-age=0' }
});

const layer = new VectorTileLayer({
  data,
  pointRadiusMinPixels: 2,
  getLineColor: [0, 0, 0, 200],
  getFillColor: [238, 77, 90],
  lineWidthMinPixels: 1,
  // tiles in this layer won't use cached results and new tiles will not be cached
});

const result = await data.widgetSource.getFormula({
  column: 'store_name',
  operation: 'count'
  // widgets from this source won't use cached results and results will not be cached
});

// etc..
```

#### **SQL API**

```shell
curl --location 'https://gcp-us-east1.api.carto.com/v3/sql/carto_dw/query?q=select%20*%20from%20carto-demo-data.demo_tables.airports' \
--header 'Authorization: Bearer ' \
--header 'Cache-Control: no-cache, max-age=0'
```

### **Method 2: Using versioning in queries and tables**

Depending on the size of your application, it might not be practical to adjust the `cache-control` header and trigger it for all requests. To ensure that the cache is fully cleared across a specific source or surface in your application, you can implement versioning in both your queries and tables.

By passing a new version, the query or table referenced will be treated as a new one by CARTO, and therefore previously cached results will not be used — All data presented in the visualization will be fresh and up to date.

{% hint style="warning" %}
Use this method carefully, and avoid sending unnecessary new versions. The cache helps your application be more performant and saves valuable computing resources, reducing costs.
{% endhint %}

#### 1. SQL Example for queries

```javascript
let version = ... // Increase the version as needed
const myDataQuery = vectorQuerySource({
  ...cartoConfig,
  sqlQuery: `WITH _version AS (SELECT ${version} AS version) 
  SELECT * FROM carto-demo-data.demo_tables.riskanalysis_railroad_accidents`,
});
```

#### 2. Example for tables

```javascript
let version = ... // Increase the version as needed
const dataSource = vectorTableSource({
  ...cartoConfig,
  tableName: `carto-demo-data.demo_tables.populated_places_${version}`
});
```

## Local browser cache

{% hint style="warning" %}
**Your browser may also be caching requests**

The local cache layer in your device/browser, or other additional cache layers may be interfering in how your HTTP requests hit the CARTO APIs and how the results are cached. Assuming that your requests are sent with `cache-control: no-cache` headers, browsers and other systems should respect this and behave accordingly.

If your content is not being cached (or not being refreshed) as you would expect to after following this guide, please check and troubleshoot other potential additional cache layers.
{% endhint %}

## Conclusions

{% hint style="success" %}
CARTO provides a cache mechanism in both cloud-based SaaS and Self-hosted deployments. This cache mechanism helps save resources. You've now learnt about our **cache defaults,** how to **adjust cache duration** in your layers and widgets, and **how to completely invalidate the cache**.
{% endhint %}
