---
title: Memory cache
slug: reference/memory-cache
docTags: 
createdAt: 2025-09-05T11:34:21.465Z
---

Factry Historian can cache time series data in memory. This will speed up queries but will consume more memory.
The memory cache is only used for internal queries and not for queries from the API. So calculations and event queries will benefit from the cache, but queries made from the frontend, the grafana datasource or the API directly will not.

Only measurements which have `consumers` are kept in the cache: if a measurement is not used in any calculations or events it will not be cached.

Only queries with supported features are able to use the cache.
The following aggregations are supported:

- `Count`
- `First`
- `Last`
- `Sum`
- `Min`
- `Max`
- `Mean`
- `Median`
- `Spread`
- `Mode`

Which means the following are not supported: `Integral`, `Stddev`, `Twa`

Aggregations are not the only requirement. A query is only served from the cache when it uses none of the following features:&#x20;

- Grouping by named tags. Only no grouping, or grouping by all tags (\*), is supported.
- Fill modes other than none and null. previous, linear and 0 are not supported.
- Value filters.
- Descending timestamp order.
- Query offsets.

A query that uses an unsupported feature is not answered by the cache but by the time series database directly, so it never returns wrong or partial data. The same applies when the cache does not fully cover the requested time range: the cache never serves a partially covered range.

## Settings

The size of the cache and whether it is enabled can be configured in the [settings page](docId\:JWpo8qZsond29MHGLErEa) of the historian.

## Guidelines

Having the cache enabled will speed up queries, but will consume more memory. Be careful when increasing the cache size, keep an eye on the memory usage of the historian and adjust accordingly.

Changing the cache size will not have an immediate effect, the cache will slowly adjust to the new size. So if you increase the cache size it will take some time before the cache is fully populated.

Numeric and boolean data are quite consistent in their size but string data can vary based on the number of unique strings. The more unique strings the more memory is used.

Below is some data on how much memory is used by different data types when 16 million data points are cached:

:::BlockQuote
**Booleans**: ±768 MiB
**Numbers**: ±896 MiB
**Strings (16K unique)**: ±772 MiB
**Strings (1M unique)**: ±946 MiB
**Strings (16M unique)**: ±3616 MiB
:::

## Statistics

The following statistics are available in the `_internal_factry` database:

- `cache_size`: The current capacity of the cache in data points.
- `cache_max_size`: The maximum size of the cache in data points.
- `cache_measurement_max_size`: The maximum size of the cache per measurement in data points.
- `cache_used`: The current amount of data points in the cache.
- `cache_consumer_count`: The number of consumers of the cache. So the number of calculations or event workers that are using the cache.
- `cache_measurement_count`: The number of measurements that are in the cache.
- `cache_hits`: The number of measurements that were served from the cache. A query over several cached measurements increments this once per measurement, not once per query.
- `cache_missed_by_error`: The number of queries that were not served from the cache due to an error.
- `cache_missed_by_feature`: The number of queries that were not served from the cache due to a feature not being supported. For example an aggregation.
- `cache_missed_by_range`: The number of queries that were not served from the cache due to the data not being in the cache.
  The following are available from version 8.2 and later:
- `cache_missed_by_missing`: The number of misses because the measurement was not in the cache at all.
- `cache_queries_hit` and `cache_queries_miss`: The query-level counters. A query counts as a hit only when every measurement in it was served from the cache.
