Open-source project
quickwit-oss/quickwit avatar
quickwit-oss/quickwit

Quickwit's ES compatibility, Kafka-gated indexing HA, and loopback dev defaults

Cloud-native OSS search engine for observability

11,790 stars628 forksRustApache-2.0

At a glance

What is it?
Quickwit is a Rust search engine for logs and traces that keeps its index on object storage such as Amazon S3, Azure Blob Storage, and Google Cloud Storage, with an Elasticsearch-compatible API and a set of production mechanisms that each stop at a specific boundary. This is a look at where those boundaries are: the ES support is a subset, indexing high availability requires Kafka, metrics are a roadmap item, and the development stack ships loopback-only port bindings.
Who is it for?
Quickwit fits teams whose observability data already lands in cloud object storage and whose log shippers speak an Elasticsearch ingest API, and it gives you search high availability without making indexers stateful. It is the wrong choice if you need metrics today, if your broker is Kinesis or Pulsar and you depend on indexing high availability, or if you need the whole Elasticsearch surface rather than the documented subset.
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 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 12, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • quickwit-oss/quickwit11,790 ★ · +125
Star history
Repository2026-09-222026-11-12
quickwit-oss/quickwit11.7k11.8k

125 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The front page still announces 0.8 while v0.9.1 carries the newest tag

The landing banner and the release list disagree, and a reader who trusts the banner installs the wrong build. The banner says the project just released Quickwit 0.8 and links a blog post about the latest features. The tags tell a different story: v0.9.3 dated 2026-10-22, v0.9.2 dated 2026-10-16 and v0.9.1 dated 2026-09-23.

That drift matters because the front page is the file most people read first. The repository root does carry a CHANGELOG.md, but the headline number is stale by at least one minor release. The repository was last pushed on 2026-11-02, after the newest tag v0.9.3 (2026-10-22), so work is landing after the newest tag as well. Read the tags and the changelog instead of the banner, and treat any 0.8 feature claim as a claim about an older build.

extra_headers lets a client believe it is talking to any Elasticsearch version

Migration is the pitch, and it comes with a documented escape hatch worth understanding before you lean on it. The claim is a large subset of the Elasticsearch and OpenSearch API, including an ES-compatible ingest API so shippers such as Vector, Fluent Bit, and Syslog can be aimed at Quickwit, plus the popular Elasticsearch endpoints, the query DSL, and aggregations on the search side. The boundary is drawn in two places: one page listing available endpoints and queries, one page listing supported aggregations.

Then there is extra_headers. When a client refuses to connect because of missing headers, the node configuration lets you impersonate any compatible version of Elasticsearch or OpenSearch. That fixes the handshake and conceals the mismatch. A client convinced it is talking to a full Elasticsearch install will not discover the subset boundary at connect time; it discovers it at the first endpoint or aggregation that is not implemented. Treat the impersonation as a transport fix. The same page also carries an estimate rather than a benchmark, that Quickwit can be up to 10x cheaper on average than Elastic, supported by a blog post about searching the web on AWS S3.

High availability for indexing arrives only when Kafka is the source

The feature list carries an asterisk that matters more than the sentence it decorates. A distributed, highly available engine that scales out in seconds is claimed, and the footnote narrows it: HA indexing only with Kafka. The FAQ section repeats the same boundary from the other direction, saying HA is available for search while for indexing it is available only with a Kafka source.

So availability splits along the ingest path, not the query path. Search is stateless, with stateless indexers and searchers and decoupled compute and storage, and that half runs against Amazon S3, Azure Blob Storage, Google Cloud Storage, and similar. Indexing does not, unless Kafka is in the picture. Kinesis and Pulsar are named as native data sources right beside Kafka, so if one of those is your existing broker the HA claim stops at the searchers and the rest becomes your problem. Multi-tenancy is listed separately as indexing with many indexes and partitioning, which is a different axis from availability entirely. The README FAQ only promises HA for search, so do not read it as a guarantee about your ingest pipeline.

Metrics are written as soon, which is not the same as shipped

The tagline reads logs, traces, and soon metrics. The feature section is blunter and says metrics support is on the roadmap. Both sentences mean the same thing, but the second is the one to plan against, because a roadmap entry is not a code path you can call.

The consequence is concrete for the audience this engine targets. A team consolidating observability wants one place to query logs, traces, and metrics, and on this version that place holds the first two. Logs come in as OTEL-native input, traces are Jaeger-native, and Grafana is offered as a data source through a separate plugin repository, so logs and traces are the two signal types the README presents as supported, while metrics is only on the roadmap. The local stack makes this easy to misread. Grafana, Prometheus, Jaeger, and an OpenTelemetry collector all appear in the compose setup alongside Postgres, Pulsar, Kafka, Localstack, and Azurite, which tells you what the project tests against, not what Quickwit can store. If metrics consolidation is the reason you are evaluating, this release does not deliver it.

Postgres is pinned to 12.17-alpine, and that build is annotated end of life

The compose file states its version policy in a comment at the top: run key services such as postgres and pulsar against the oldest supported version, run Kafka against the oldest version that supports KRaft, and run everything else against the latest. The default in the postgres service is postgres:${POSTGRES_VERSION:-12.17-alpine}, and that service carries its own comment marking it as the oldest supported version with an end of life date of November 14, 2024. The policy is deliberate and reasonable for compatibility testing.

The .env.example works against the same defaults rather than with them. Its header says to update all services to the latest versions, and it sets:

code
POSTGRES_VERSION=latest
PULSAR_VERSION=latest
CP_VERSION=latest
AZURITE_VERSION=latest
JAEGER_VERSION=latest
OTEL_VERSION=latest
PROMETHEUS_VERSION=latest

Copy that file and you get a different Postgres than the compose default, quietly. The database itself is named quickwit-metastore-dev.. The Makefile does give you a way to destroy it while iterating:

code
docker volume rm quickwit_azurite_data quickwit_fake_gcs_server_data quickwit_grafana_conf quickwit_grafana_data quickwit_localstack_data quickwit_postgres_data

Every port binds to loopback until you edit the env file, and that env file holds dev passwords

The compose file states the rule in its opening lines: by default it maps all services to localhost only, and services become reachable from outside the machine only if you add the right mappings to the .env file. The port definitions back that up with a defaulting variable, for example ${MAP_HOST_LOCALSTACK:-127.0.0.1}:4566:4566, the same shape on 4571 and 8080, where the fallback resolves to the loopback address whenever the variable is unset. Starting a subset instead of everything works by compose profile, which is why the Makefile parameterizes it:

code
make docker-compose-up DOCKER_SERVICES='jaeger,localstack'

The .env.example is where the risk sits, because that is the file a newcomer copies first. Under the heading Expose the services to outside network it sets MAP_HOST_LOCALSTACK, MAP_HOST_POSTGRES, MAP_HOST_PULSAR, MAP_HOST_KAFKA, MAP_HOST_ZOOKEEPER, MAP_HOST_AZURITE, MAP_HOST_GRAFANA, MAP_HOST_JAEGER, MAP_HOST_OTEL, and MAP_HOST_PROMETHEUS all to 0.0.0.0. The same file holds placeholder Postgres credentials, and these lines set them:

code
POSTGRES_USER=quickwit-dev
POSTGRES_PASSWORD=quickwit-dev
POSTGRES_DB=quickwit-metastore-dev

Ten services listening on every interface with a shared placeholder password is unremarkable on a laptop and wrong on a shared host. Localstack shows the same two-speed policy as Postgres: the compose default pins it to 3.5.0, while the env example moves it to 4.14.0 with a note that this is the last free version.

The image tag comes from your branch name and bin is filled by sweeping the target directory

Building the container is a three stage affair with every base pinned to a digest. A node:26 stage copies quickwit/quickwit-ui and runs make install build under NODE_ENV=production. A rust:bookworm stage installs ca-certificates, clang, cmake, libssl-dev, llvm, and protobuf-compiler, copies the quickwit directory plus config/quickwit.yaml, runs rustup toolchain install, and then builds with RUSTFLAGS set to --cfg tokio_unstable, targeting the quickwit-cli package, a feature set defaulting to release-feature-set, and the quickwit binary, with a release flag added when the profile is release. Commit date, commit hash, commit tags, and a lambda zip path all arrive as build arguments and are passed into the image as environment values.

Two details carry consequences. The build finishes by moving every executable found one level below the target directory into /quickwit/bin, using find with a permission test, rather than copying one named artifact, so what ends up in that folder depends on what the workspace happened to leave in target. And the image tag is derived from the current git branch with slashes and hashes rewritten to dashes, then applied as quickwit/quickwit plus that value. A build from a feature branch yields an image labelled with the branch, not with a version, so image provenance in your registry depends on how you invoked the build. The final stage is debian:bookworm-slim, and the image labels name Quickwit as the title with Quickwit, Inc. as maintainer.

Editorial conclusion

Quickwit fits teams whose observability data already lands in cloud object storage and whose log shippers speak an Elasticsearch ingest API, and it gives you search high availability without making indexers stateful. It is the wrong choice if you need metrics today, if your broker is Kinesis or Pulsar and you depend on indexing high availability, or if you need the whole Elasticsearch surface rather than the documented subset. Before committing, read the two compatibility reference pages rather than the headline claim, check whether metrics support has reached a release rather than the roadmap, and read your own broker against the HA footnote before planning a failover.

Frequently asked questions

What is Quickwit and what is it built for?

It is a cloud-native open-source search engine for observability, written in Rust, that targets logs and traces kept on cloud object storage such as Amazon S3, Azure Blob Storage, and Google Cloud Storage. It offers full-text search and aggregation queries, schemaless or strict schema indexing, an Elasticsearch-compatible API, and a Grafana data source. Metrics support is on the roadmap.

Is Quickwit open source?

Yes. It is released under the Apache License, Version 2.0, identified as Apache-2.0, and the primary language is Rust. The default branch is main and the project home is quickwit.io.

Is Quickwit dead?

No sign of that in the repository state. It is not archived and the last push is dated 2026-11-02. Recent releases include v0.9.3 from 2026-10-22, v0.9.2 from 2026-10-16 and v0.9.1 from 2026-09-23, so releases landed well after the README banner announcing version 0.8.

Is Quickwit free to run?

The license is Apache-2.0. On cost the project states an estimate that Quickwit can be up to 10x cheaper on average than Elastic, and points to a blog post about searching the web on AWS S3 for the reasoning. That is the project's own estimate rather than an independent measurement.

How does Quickwit compare to Loki?

The README FAQ names Elasticsearch and Solr as the traditional search engines it differs from, and explains the difference as an architecture built from the ground up to search on cloud storage, with optimized IO paths and revamped index data structures.

How does Quickwit compare to OpenSearch?

Quickwit supports a large subset of the Elasticsearch and OpenSearch API, including an ES-compatible ingest API and the query DSL and aggregations on the search side. Two reference pages list the available endpoints and queries and the supported aggregations. If a client rejects the connection over missing headers, the node configuration offers an extra_headers option to impersonate any compatible version of Elasticsearch or OpenSearch.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. quickwit-oss/quickwit on GitHub
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/quickwit-oss-quickwit.svg)](https://hysenlabs.com/projects/quickwit-oss-quickwit)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/quickwit-oss-quickwit.svg)](https://hysenlabs.com/projects/quickwit-oss-quickwit)

Was this useful?