Apache Pinot: a column-oriented OLAP datastore for user-facing dashboards
Apache Pinot - A realtime distributed OLAP datastore
At a glance
- What is it?
- Built at LinkedIn to serve hundreds of thousands of queries per second at millisecond latency. The cost is a columnar model that assumes your queries are aggregates, not row lookups.
- Who is it for?
- Pinot fits when a user-facing interface needs aggregates over petabyte data at a latency people will keep clicking on, which is the workload it was built for at LinkedIn. It does not fit when you need point lookups by primary key, secondary indexes over high cardinality string columns you did not plan for, or SQL general enough to treat it as a drop-in replacement for a warehouse.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Designed for dashboards people keep clicking on
The README is unusually specific about the workload, and the specificity is the most useful thing on the page. Pinot powers 50 or more user-facing products at LinkedIn, ingesting millions of events per second and serving 100k or more queries per second at millisecond latency, with P90 latencies in the tens of milliseconds. UberEats Restaurant Manager is named as a customer facing example from Uber.
That origin explains the architecture better than any marketing line would. A dashboard that a person interacts with is a different problem from a report you run overnight. It has unpredictable cardinality of queries, a hard latency budget measured in tens of milliseconds, and a concurrency profile that is hundreds of thousands of queries per second rather than a handful of long ones. Pinot's design target is stated as constant performance based on cluster size and an expected QPS threshold, which is the promise of an OLAP engine built for serving rather than for batch scanning.
So when you evaluate Pinot, the question is not whether it can answer SQL. It can, through a built-in query editor and a REST API. The question is whether your queries have the shape this engine is good at, which is filter and aggregate over large columnar segments.
Ingest that merges streams and batch files into one table
Pinot ingests from both sides. Stream sources named in the README are Apache Kafka, Apache Pulsar and AWS Kinesis, ingested in real time. Batch sources are Hadoop, Spark, AWS S3 and more, and the README names Hadoop HDFS, Amazon S3, Azure ADLS and Google Cloud Storage as the batch sources.
The line worth pausing on is that batch and streaming sources can be combined into a single table for querying. That is the feature that separates Pinot from older generation real-time engines, where the streaming table and the dimension data lived in different systems and the join happened outside the database. Upsert during real-time ingestion is listed with the note that it updates data at scale with consistency, and the 1.5.0 release added offline table support for upsert along with commit-time compaction, which suggests the real-time and offline paths have been converging rather than staying separate.
The repository layout reflects how many moving parts this creates. There is a `pinot-broker/` for stream consumption, `pinot-controller/` for cluster and schema management, `pinot-server/` for query serving and storage, `pinot-core/` and `pinot-segment-local/` for the storage engine, `pinot-minion/` for background work, `pinot-connectors/` for the ingest sources, and `pinot-plugins/` for the extension points. Also present is `pinot-materialized-view/`, a newer module that does not appear in the release notes above.
Index choice is a schema decision, not a query decision
Pinot's indexing is pluggable and the README lists the options: timestamp, inverted, StarTree, bloom filter, range, text, JSON and geospatial. Each has a link to its own documentation page under docs.pinot.apache.org.
This is the concept that most changes how you use the system. In a general purpose database you add an index when a query turns out to be slow. In Pinot the index is attached to a column in the schema, so the decision about what to index happens at design time, before you know which queries your users will write. Get it wrong and the query is not slower, it is unanswerable within the latency budget, because a full scan across petabytes will not return results in tens of milliseconds.
StarTree is the interesting one for the dashboard case named in the README, since its purpose is pre-aggregating on chosen dimensions so a filter-and-group query can be answered from the pre-aggregated result rather than from raw data. Text and JSON indexing cover the case where the field you need to filter on is free text or a nested object, which is common in event data. The trade-off across all of them is memory and ingest cost against query speed, and the README gives no numbers for any of it, so this is a topic where the documentation on docs.pinot.apache.org rather than the README is what you need.
Two query engines arrived, and the choice is not cosmetic
The 1.4.0 release notes describe a new query mode added for running multistage engine queries against Pinot, and they are candid about what it is: a beta feature heavily inspired by Uber's Presto over Pinot architecture. MSE Lite Mode follows a Scatter-Gather paradigm like the original engine, and adds a configurable limit on records returned by each instance of the leaf stage, set to 100k records by default.
The motivation given in the notes is access control rather than performance. With the limit in place, the release says you can enable multistage engine access for all users without worrying about them breaking production workloads, and the claim is that the mode scales to thousands of QPS with minimal hardware.
The 1.5.0 notes then push it further: native `CROSS JOIN UNNEST(...)` support with optional `WITH ORDINALITY` for flattening array columns, an enriched join operator with improved execution strategies, aggregation rewrites, and Kafka 4.x support. Over 1100 commits went into that release. A separate federation and multi-cluster routing framework also arrived in 1.5.0, which is what you would need to query across more than one Pinot cluster.
Practically this means a new Pinot deployment has two engines to choose between and a beta tag on one of them. The original engine is the safe default for the dashboard workloads Pinot was built for.
Getting a cluster running from what the repository contains
The README points to docs.pinot.apache.org for getting started guides and deployment recipes, and the repository ships the pieces for three routes: a Maven wrapper for building, a `docker/` directory, and a Helm chart under `helm/` for Kubernetes.
For a local build, the wrapper is the entry point, since the repository carries `mvnw` and `mvnw.cmd` rather than assuming a system Maven:
git clone https://github.com/apache/pinot
cd pinot
mvnw installThe `docker/` directory at the repository root holds the compose setup, which is the shortest route to something you can query:
cd docker
docker compose upFor Kubernetes, the README's description of the Helm chart is that it provides a horizontally scalable and fault-tolerant clustered deployment that is easy to manage using Kubernetes. There is a `helm/` directory in the tree to go with it, along with `config/`, `scripts/` and `tools/`.
One structural note. The test workflows named in the badges at the top of the README are separate for unit tests, integration tests, quickstart tests and compatibility checks, and the tree includes a `pinot-compatibility-verifier/` and a `compatibility-verifier/` module. For a datastore that stores data in its own segment format, a compatibility verifier is not decoration: it is how you find out whether an upgrade can still read what you already wrote.
Upgrade path and the honest comparison
The release sequence is regular. 1.4.0 was published on 2025-09-15, 1.5.0 on 2026-04-09, and 1.5.1 on 2026-06-05. Nothing is archived and the last push was on 2026-09-22, so this is an active Apache project on a steady cadence.
1.5.1 is worth reading closely because it is the kind of release that tells you how the project handles security. It is described as a security patch release based on 1.5.0, containing only dependency updates and dependency-exclusion changes to resolve reported CVEs, with no functional, API, configuration or wire-format changes. The notes list the specific dependency bumps and the CVEs each addresses, across Netty, Log4j Core, async-http-client, HttpClient 5, Pulsar with BouncyCastle, and commons-configuration2, and report that a vulnerability scan of the 1.5.1 binary distribution found zero critical and zero high findings. Licence is Apache-2.0, with both `LICENSE` and `LICENSE-binary` plus matching NOTICE files in the tree.
The comparison people actually ask about is with Druid and ClickHouse. The distinction is arrival. Pinot takes both streams and batch files into one queryable table and is optimised for a high-concurrency serving workload behind an interactive UI. ClickHouse and Druid are both strong analytical stores, and either will beat Pinot on heavy aggregation over historical data. Pinot's specific claim is the interactive, high-QPS, millisecond-latency end, and that is where you should hold it to account.
Editorial conclusion
Pinot fits when a user-facing interface needs aggregates over petabyte data at a latency people will keep clicking on, which is the workload it was built for at LinkedIn. It does not fit when you need point lookups by primary key, secondary indexes over high cardinality string columns you did not plan for, or SQL general enough to treat it as a drop-in replacement for a warehouse. Two things to check before committing: the indexing choice per column, since pluggable indexes are configured at schema level and change what queries are cheap, and the query engine you use, since 1.4.0 introduced a multistage engine in beta and 1.5.0 extended it with UNNEST and enriched joins. The last push was 2026-09-22, and 1.5.1 is a security patch release with no functional changes.
Frequently asked questions
What is Apache Pinot used for?
It is a real-time distributed OLAP datastore for user-facing analytics interfaces. The README says it powers 50 or more products at LinkedIn, ingesting millions of events per second and serving 100k or more queries per second at millisecond latency, and it takes both Kafka style streams and batch files from HDFS, S3, ADLS or GCS into a single queryable table.
Which indexes does Apache Pinot support?
The README lists timestamp, inverted, StarTree, bloom filter, range, text, JSON and geospatial as pluggable indexing technologies. Because indexes are attached to columns in the schema rather than added at query time, the choice is made when you design the table.
What changed in Apache Pinot 1.5.0?
The 1.5.0 release notes describe over 1100 commits covering the multistage query engine with UNNEST support and enriched joins, upsert for offline tables with commit-time compaction, a federation and multi-cluster routing framework, Kafka 4.x support, new index types including N-gram and IFST, and query resource isolation. It was published on 2026-04-09.
Is Apache Pinot 1.5.1 a functional upgrade?
No. The release notes state it is a security patch release based on 1.5.0 with only dependency updates and dependency-exclusion changes, and no functional, API, configuration or wire-format changes. Dependency bumps cover Netty, Log4j Core, async-http-client, HttpClient 5, Pulsar and commons-configuration2.
How do you deploy Apache Pinot on Kubernetes?
With the Helm chart in the repository's `helm/` directory, which the README describes as providing a horizontally scalable and fault-tolerant clustered deployment managed through Kubernetes. The repository also carries a `docker/` directory for a local compose setup and `mvnw` for building from source.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/apache-pinot)Was this useful?