1. Overview
This document describes how Parquet data cache and Pinot index cache work in case of External tables as well as regular tables configured with remote tiered storage. External tables read their data from object storage on every query. The Parquet Data Cache keeps recently-read Parquet pages on the server so subsequent queries do not pay the round-trip. Indexes for both external tables and Pinot tiered storage tables also live on object storage. The Index Cache keeps recently-read index byte ranges on the server.
Both caches share the same underlying machinery and, by default, the same in-memory sizing configuration (it isn’t scoped per cache):
- Parquet Data Cache populates an in-memory prefetch tier (decompressed, decoded values on heap, default 1 GB) in front of an mmap-backed disk tier (default 30% of disk).
- Index Cache populates an in-memory raw-bytes tier (the same underlying memory cache used by the Parquet Data Cache — default 256 MB data / 64 MB dictionary, since the memory-size configs aren’t per-consumer) in front of its own mmap-backed disk tier. Only the 1 GB prefetch tier is effectively Parquet-Data-Cache-only, since raw index byte ranges have no decoded form to keep there.


2. What’s enabled out of the box
2.1 Parquet Data Cache — always on
This cache is always on and does not need to be explicitly enabled. The cache is created at server startup and serves every read against a remote-Parquet column.2.2 Index Cache — opt-in per query
The Index Cache is populated only when a query is preceded by
Without the query option and without StarTree bitmap reads, the Index Cache stays empty and the directory remains untouched.
3. Advanced operations: Enable, disable, skip
3.1 Parquet Data Cache
Always on at the server level and cannot be globally disabled. However, you can use a per-query bypass as shown below:3.2 Index Cache
In this case, there is no global enable flag; enablement is a per-query decision. You can enable index cache for a specified query as shown below:
As mentioned previously, once set, subsequent queries can benefit from this index cache as applicable.
3.3 Footer Cache
The Footer Cache stores the Parquet file footer (row-group metadata and schema) for each segment so it doesn’t need to be re-fetched from object storage on every query. It is enabled by setting a segment cache directory:parquet_footer.bin in that directory and reloaded on server restart (controlled by pinot.server.instance.segment.cache.load.existing.cache, default true). Without this setting, the footer is fetched from remote storage on each query.
For the full list of footer cache configuration keys, see Best Practices and Configs.
4. Behavior on restart
The on-disk tier is wiped on server startup by default. To keep cached data across restarts, set the following cluster config — there’s no JVM-D equivalent:
5. Eviction policies
When the disk tier is full, the oldest fragment file is unmapped and deleted; new pages are written to a fresh fragment.
TTL-based eviction (optional)
By default the disk tier only evicts under space pressure, so cold entries in a cache that never fills can stay on disk indefinitely. You can additionally enable TTL eviction, which reclaims idle or old entries on every eviction sweep regardless of fullness. Both configs are off (0) by default and apply to both caches.
TTL eviction runs as part of the background sweep, so the eviction interval must be non-zero for it to take effect.
On server restart, entries restored from a snapshot reset their TTL clock to load time, so a restart never prematurely evicts cached entries.
Disk cache configuration reference
The following cluster-config keys tune the disk tier (shared by both caches). All keys also accept a per-consumer suffix to target a single cache, e.g.pinot.parquet.page.cache.disk.ttl.write.ms.SEGMENT_INDEX or ...PARQUET_INDEX.
6. Clearing caches
HTTP endpoints
There are certain scenarios in which user may want to clear the caches. StarTree provides Cluster-wide APIs for this (controller fans out to every server):
This can also be done via a per-server API (skip the controller, hit one server directly):

