# Quickwit: a Rust search engine that keeps its index on object storage

> Quickwit is an Apache-2.0 search engine for logs and traces that stores its index in S3, Azure Blob Storage or Google Cloud Storage and splits indexing from search. It suits teams already paying for a bucket and tired of running stateful search nodes, and it is the wrong tool if you need metrics today.

**quickwit-oss/quickwit** — Cloud-native OSS search engine for observability

- Repository: https://github.com/quickwit-oss/quickwit
- Website: https://quickwit.io
- Stars: 11,688 · Forks: 607
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/quickwit-oss-quickwit

## The problem Quickwit targets: search where the data already lives

Most log platforms assume the index sits on local disks attached to the search nodes. That assumption drives the cost model: you pay for storage on those nodes, you pay for replication so a lost node does not lose a shard, and you pay again when you scale out because rebalancing moves data across the network. Quickwit starts from the opposite premise. The index is written to object storage (the README lists Amazon S3, Azure Blob Storage and Google Cloud Storage), and both indexers and searchers are described as stateless. A searcher that dies does not take a shard with it; a new one reads the same objects.

The intended audience is narrow and specific. The README frames the project as an observability engine for logs and traces, with metrics listed as a roadmap item rather than a shipped feature. So the fit is a platform team that already ships logs and traces into a bucket or a stream, wants full-text search and aggregation over them, and would rather not operate a cluster whose storage grows with retention. It is not a general-purpose application search backend, and the README does not present it as one.

## How the split between indexers, searchers and the metastore works

The architecture image in the README shows the pieces: indexers, searchers, a metastore, and object storage underneath. Indexers consume from a source (the README names Kafka, Kinesis and Pulsar as native data sources, plus an OTEL path for logs and traces), build index splits, and publish them to object storage. Searchers do not own splits; they discover them through the metastore and read them from storage. That is what makes the searchers stateless and what the README means when it claims sub-second search on cloud storage.

The metastore is the piece that decides whether this is a single-node experiment or a real deployment. The repository's docker-compose.yml runs a postgres service and the .env.example sets POSTGRES_USER, POSTGRES_PASSWORD and POSTGRES_DB to quickwit-dev, quickwit-metastore-dev and similar values, which tells you Postgres is a supported metastore backend rather than an optional extra. The same compose file defines a localstack service with SERVICES set to kinesis,s3,sqs, so the local development path emulates S3 and Kinesis rather than mocking them in process.

Two consequences follow. First, the search path's latency depends on object storage request latency, not on page cache, so the design trades a predictable local-disk read for a network round trip. Second, the number of indexers is decoupled from the number of searchers, which is the property that lets the README claim the engine "scales out in seconds". The README qualifies high availability: search is HA, but indexing is HA only with a Kafka source. If your ingestion is a batch job or a single collector writing directly, you have a single point of failure in the ingest path that the architecture does not remove.

## Installing Quickwit and running a first query

The README points installation at https://quickwit.io/docs/get-started/installation and the quickstart at https://quickwit.io/docs/get-started/quickstart, so the canonical download path is the project site rather than a package manager. The repository also carries an install.sh at the top level, which is the script the site presumably serves.

For a local run, the repository ships a docker-compose.yml. The Makefile wraps it: `make docker-compose-up` starts every service, and you can narrow it to a subset by profile, for example `DOCKER_SERVICES='jaeger,localstack'`. Note that the compose file maps services to 127.0.0.1 by default; the .env.example shows how to widen that by setting variables such as MAP_HOST_LOCALSTACK=0.0.0.0.

```bash
make docker-compose-up DOCKER_SERVICES='jaeger,localstack'
```

You should see the localstack container come up with kinesis, s3 and sqs enabled and a healthcheck against https://localhost:4566/quickwit-integration-tests. The Makefile also offers `make docker-compose-down` to tear the stack down and `make docker-compose-logs` to follow output.

To build the binary and container image yourself, the Makefile computes the commit metadata and passes it as build arguments:

```bash
make docker-build
```

That runs `docker build` with QW_COMMIT_DATE, QW_COMMIT_HASH and QW_COMMIT_TAGS derived from git and tags the result quickwit/quickwit:<branch>. The Dockerfile behind it is a multi-stage build: a node:24 stage builds quickwit/quickwit-ui, a rust:bookworm stage compiles the quickwit-cli package with the release-feature-set feature and RUSTFLAGS="--cfg tokio_unstable", and a debian:bookworm-slim stage carries the final image. Expect the Rust stage to be the slow part, since it installs clang, cmake, libssl-dev, llvm and protobuf-compiler before compiling.

Once a node is up, the README says the REST API and an Elasticsearch-compatible API are both available, so the first real query can go through whichever client you already use. The README notes that if a client refuses to connect because of a version header mismatch, the node configuration has an `extra_headers` option under the REST configuration that lets you impersonate a compatible Elasticsearch or OpenSearch version.

## Where Quickwit is the wrong tool

Metrics. The README lists metrics support as "on the roadmap" and the headline describes the engine as covering logs and traces. If your observability stack is one PromQL-compatible store for everything, Quickwit is not that store today, and adopting it means running a second system alongside whatever handles metrics.

The Elasticsearch compatibility is a subset, and the README says so twice: "a large subset" of the API, with the endpoint list and the aggregation list published separately. That is a real migration risk. A dashboard that leans on an unsupported aggregation will not fail loudly at install time; it will fail when someone opens that panel. The README's own mitigation is the `extra_headers` trick for clients that reject the server, which solves a handshake problem and not a query-coverage problem.

High availability for indexing depends on Kafka. The README states plainly that HA indexing is available only with a Kafka source. If you ingest through a single Fluent Bit or Vector instance pushing to the ingest API, the storage layer is durable but the writer is not, and Quickwit does not change that.

Finally, the search path is bound to object storage latency. The README's claim of sub-second search on cloud storage is a claim about the engine's IO paths, not a guarantee for your query. A broad regex over a large retention window still has to read splits from a bucket. There is no documented rollback procedure in the README either, so an index-format upgrade is something to plan around rather than assume is reversible.

## Quickwit against Elasticsearch, Loki and ClickHouse

Elasticsearch and OpenSearch keep index shards on the data nodes and replicate them. Quickwit keeps splits in object storage and keeps the nodes stateless. The practical difference is what you scale and what you pay for: with Elasticsearch, retention means disk on the cluster; with Quickwit, retention means bytes in a bucket plus whatever the metastore tracks. The README also leans on the API overlap as the migration story, which only works because Quickwit accepts Elasticsearch clients at all.

Grafana Loki shares the object-storage premise but indexes labels rather than full text. Loki's query model rewards you for choosing labels well and punishes you for searching log bodies broadly. Quickwit indexes the content, which is why the README can advertise full-text search and aggregation queries rather than label matching. The trade is index size and ingest work: you are building a real inverted index, not a label map.

ClickHouse is a columnar analytical database that many teams use for logs. It gives you SQL and fast aggregation over columns, and it is not a full-text search engine in the same sense. Quickwit's pitch is closer to search plus aggregation over text, with an Elasticsearch-shaped API and Jaeger and OTEL integrations rather than a SQL surface.

Tantivy is worth naming because it is the same organisation's Rust search library and one of the repository's topics. Quickwit is the distributed system built around that kind of indexing; if you want an embedded library rather than a cluster with a metastore and object storage, they are different products.

## Maintenance, releases and what Apache-2.0 means here

The last push to the default branch was on 2026-09-21, and the repository is not archived. Recent releases include v0.9.0 on 2026-07-25, an earlier tag on 2026-05-20 and a lambda tag on 2026-04-21. The README's own banner still announces Quickwit 0.8 and links a blog post about it, which is a documentation lag worth noting: the top of the README is not the newest information in the repository, and the CHANGELOG.md at the root is the better place to look for what changed.

The upgrade surface has three parts. The binary and container image, which the Makefile tags by branch name, so a branch-derived tag is not a version you can pin to a release. The index format, which is the one that matters most, since an on-disk format change forces a reindex or a compatibility path, and the README does not document rollback. And the metastore schema, which is why the Makefile carries a `migrations-lint` target under the quickwit source directory: schema migrations are part of the operational story, not an afterthought.

Licensing is Apache-2.0, confirmed by the LICENSE file at the root and the badge in the README. Two details are easy to miss. The repository includes a LICENSE-3rdparty.csv, so dependency licences are enumerated rather than assumed. And the project ships an AI_POLICY.md alongside CONTRIBUTING.md, which means contribution rules around generated code exist and are worth reading before you send a patch. None of this is legal advice; if your organisation has a policy on Apache-2.0 dependencies or on the patent grant that comes with it, that review is yours to run.

## Conclusion

Adopt Quickwit if your logs or traces already land in an object store and you want search nodes that hold no local index state; skip it if you need metrics now, or if your indexing path must survive a broker outage without Kafka, since the README states HA indexing is available only with a Kafka source. Before committing, verify two things against your own data: which Elasticsearch endpoints and aggregations your clients actually call, because Quickwit supports a subset, and whether the ingest path you use (Kafka, Kinesis, Pulsar, or an OTEL collector) is one the ingest documentation covers.

## FAQ

### Is Quickwit open source?

Yes. The README states Quickwit is open-source under the Apache License, Version 2.0, and the repository carries a LICENSE file plus a LICENSE-3rdparty.csv listing third-party licences.

### Is Quickwit free?

The README gives the licence as Apache-2.0 and does not describe a paid tier or a hosted-only edition. The download and installation links point at the project site.

### What is Quickwit?

The README describes it as an open-source search engine for observability, covering logs and traces, with metrics support listed as a roadmap item. It offers full-text search and aggregation queries over data indexed to cloud storage.

### How does Quickwit compare to Loki?

Both put their index in object storage, but the README positions Quickwit around full-text search and aggregation queries over logs and traces rather than label-based log matching. Quickwit also exposes an Elasticsearch-compatible API and is Jaeger-native and OTEL-native.

### How does Quickwit compare to OpenSearch?

The README says the core difference is an architecture built to search on cloud storage, with stateless searchers and optimised IO paths. Quickwit supports a large subset of the Elasticsearch and OpenSearch API, and the supported endpoints and aggregations are listed separately in the documentation.

## Sources

- [License: Apache-2.0](https://github.com/quickwit-oss/quickwit/blob/main/LICENSE)
- [Project website](https://quickwit.io)
- [quickwit-oss/quickwit on GitHub](https://github.com/quickwit-oss/quickwit)
- [README](https://github.com/quickwit-oss/quickwit/blob/main/README.md)
- [Releases](https://github.com/quickwit-oss/quickwit/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/quickwit-oss-quickwit
