Hi, glad to know that you're interested in contributing to QuestDB. Here are some topics that can help you get started:
- 📜 License and conduct
- 🎯 Contribution expectations
- 💡 Bugs and features
- 🧭 Navigation
- 🔧 Environment setup
- ✅ Before you submit
- 📢 For maintainers
By contributing to QuestDB, you agree that your contributions will be licensed under the Apache License 2.0. No CLA or DCO signature is required.
Please review our Code of Conduct before participating. We are committed to providing a welcoming and inclusive environment for everyone.
QuestDB is a production-grade system serving critical use cases. All contributions must meet high standards for quality and reliability. Please read this section carefully before starting any work.
- Exhaustive testing required — every contribution must include comprehensive tests
- Problem-focused changes only — contributions must solve a real problem; superficial changes (spelling fixes in comments, whitespace adjustments, stylistic tweaks) are not accepted
- Minimize change surface area — keep changes focused and minimal to reduce risk
- Additive and non-breaking — make every effort to avoid breaking existing behavior; if a breaking change is truly unavoidable, join Slack to discuss it before starting implementation
- No architectural changes without discussion — large-scale or structural changes must be discussed in an issue before implementation begins
Changes that affect core data paths, storage formats, or wire protocols are considered high-risk. These require prior discussion and approval from maintainers before any code is written.
QuestDB Inc maintains QuestDB Open Source. We use GitHub issues internally for planning. We reserve the right to prioritize any issue according to our roadmap, even if a contribution is in progress but proceeding slower than required.
Whether it's a bug report or feature request, you're welcome to raise an issue using the respective template.
If you're not sure whether you should raise an issue, you can also join our community Slack channel and post your questions there.
If you find any security bug, kindly refer to SECURITY.md for more info.
We aim to respond to your issues and questions as soon as possible. To help us respond faster, please always describe your steps and provide information about your environment in bug reports. If you're proposing a new feature, it helps us evaluate priority if you explain why you need it.
Before commenting on an issue to claim it, make sure you have read and understood the contribution expectations section above. Once you are confident you can meet the requirements, comment on the issue to let maintainers know you're working on it.
- QuestDB database and libraries source in Java:
core/src/main/java/ - QuestDB database tests:
core/src/test/java/ - QuestDB libraries in C:
core/src/main/c/ - QuestDB Windows service wrapper:
win64svc/ - QuestDB web console (frontend):
github.com/questdb/ui - Micro benchmarks:
benchmarks/
Compiled binaries (for C libraries and Windows service wrapper) are committed to git to make the development process Java‑centric and simpler.
Our maintainers label issues with relevant categories so you can use that to
search for certain types of issues you'd like to work on. If you don't know where
to start, try searching for issues labeled with
good first issue
or help wanted. If
you wish to understand how our maintainers work together, you can refer to
this section.
- Operating system - x86-64 or ARM64: Windows, Linux, FreeBSD, and macOS
- Java 17 64-bit (strict requirement — no earlier, no later)
- Maven 3 (latest version recommended; from your package manager on Linux/macOS (Homebrew) or from the jar for any OS)
- C compiler, CMake — to contribute to C libraries — OPTIONAL
Note for Apple Silicon (ARM64) users: Most tests will run normally. However, JIT-related tests are x86-64 only and will be skipped on ARM. If you are contributing to JIT functionality, use an x86-64 machine or run an x86-64 JDK under Rosetta emulation.
JAVA_HOME is required by Maven. It is possible to have multiple versions of
Java on the same platform. Please set up JAVA_HOME to point to Java 17.
Other versions of Java will not work. If you are new to Java please check
that JAVA_HOME is pointing to the root of the Java directory:
C:\Users\me\dev\jdk-17 and not C:\Users\me\dev\jdk-17\bin\java.
Linux/macOS
export JAVA_HOME="/path/to/java/"Windows
set JAVA_HOME="c:\path\to\java directory"You can compile the database and build the web console with the following command:
mvn clean package -DskipTests -P build-web-consoleYou can then run QuestDB with:
java -p core/target/questdb-<version>-SNAPSHOT.jar -m io.questdb/io.questdb.ServerMain -d <root_dir>The web console will be available at localhost:9000.
Code is formatted using configuration files in the .idea directory.
To minimize conflicts when merging and problems in CI, all contributed code should be formatted
before submitting a PR.
In IntelliJ IDEA you can:
- Automate formatting (preferable):
- Open File | Settings
- Choose Tools | Actions on Save
- Select Reformat and Rearrange Code
- Click Apply
- Or format files manually by selecting them and choosing Code | Reformat File.
We recommend using IntelliJ IDEA for development and debugging. The repository
includes run configurations in the .idea directory that you can use to start
QuestDB with a debugger attached.
C libraries will have to be compiled for each platform separately. CMake will
also need JAVA_HOME to be set. The following commands will compile on
Linux/macOS.
cd core
cmake -B build/release -DCMAKE_BUILD_TYPE=Release .
cmake --build build/release --config Release
For more details, see CMake build instructions.
For C/C++ development we use CLion. This IDE understands CMake files and makes compilation easier.
The build will copy artifacts as follows:
core/src/main/c -> core/src/main/resources/io/questdb/bin
The QuestDB server tests use the Java ILP client for integration testing. By default, the client is resolved from Maven Central. If you need to modify both the client and server simultaneously, you can use the local development workflow.
The Java client is available as a git submodule in java-questdb-client/. Initialize it with:
git submodule update --init java-questdb-clientUse the local-client profile to build the client from the submodule and use it in tests:
mvn test -P local-clientThis will:
- Build the client from
java-questdb-client/first - Use the locally built client (version
1.0.1-SNAPSHOT) for server tests
To work on both the client and server in IntelliJ IDEA:
- Initialize the submodule (see Setup above)
- Open IntelliJ IDEA and go to File > Project Structure > Modules
- Click + (Add) > Import Module
- Select
java-questdb-client/core/pom.xmland click OK - IntelliJ will import the client module alongside the server modules
- In the Project view, you can now navigate and edit both codebases
To ensure IntelliJ uses the local client instead of the Maven Central version:
- Open the Maven tool window (usually on the right side, or via View > Tool Windows > Maven)
- Expand Profiles and check
local-client - Click the Reload All Maven Projects button (circular arrows icon)
Now when you run tests from IntelliJ, they will use your local client changes.
- Make changes to both
java-questdb-client/andcore/as needed - Run tests with
-P local-clientto verify everything works together - When done, commit changes to each repository separately
- The client submodule changes should be pushed to the java-questdb-client repository
The frontend code (i.e. web console) is located in a separate repository. To set it up you should follow the instructions provided in that repository.
The development environment for the frontend can run on its own, but it requires a QuestDB instance running in the background. You can achieve this in multiple ways:
- Run a development version of QuestDB from this repository. Consult the environment setup section of this document.
- Run a published QuestDB version, for example with Docker. More details can be found in the README of this repository.
We have a lot of tests, most of which are of the "integration" type (e.g., a test starts a server, interacts with it, and asserts the outcome). We expect all contributors to submit PRs with tests. Please reach out to us via Slack if you're uncertain how to test, or you think an existing test can be improved.
Typical Maven commands:
- Run full test suite:
mvn test- Run a specific test class:
mvn -Dtest=ClassNameTest test- Run a specific test method:
mvn -Dtest=ClassNameTest#methodName testFor changes that may impact performance, you must benchmark before and after your changes. Use the row generator functions to create large datasets for meaningful measurements. Include data volume and performance figures (before/after) in your PR description.
QuestDB does not have third-party Java dependencies. This may sound unorthodox; in reality we try not to reinvent the wheel, but rather than using libraries we implement algorithms on first principles to ensure a perfect fit with existing code. With that in mind, we expect contributions not to add third-party dependencies.
QuestDB is zero-GC along critical paths. We expect contributions not to allocate if possible. Here are the key principles:
- No allocations on critical paths — query execution and data ingestion must not trigger garbage collection
- No string concatenation — use the builder pattern (e.g.,
StringSink) instead of+orStringBuilder - No string creation — work with
CharSequence,Utf8Sequence, or direct memory where possible - Safe object reuse and pooling — reuse objects rather than creating new ones; use existing pool implementations
- No throwing
newexceptions — use pre-allocated exception instances or error codes on hot paths - Use QuestDB collections and primitives — avoid JDK collections (
ArrayList,HashMap, etc.); use QuestDB's internal implementations (ObjList,CharSequenceIntHashMap, etc.) - Use QuestDB utilities — we have built-in tools for comparison, number parsing, and UTF-8 handling; use these rather than JDK equivalents
- Watch out for lambdas — lambdas can allocate; cache them if you must use them
If you're unsure how to achieve zero-GC for your contribution, reach out via Slack.
We use Conventional Commits to auto-generate release notes. We require all commit messages to conform. To that end, commits have to be granular enough to be successfully described using this method.
Example:
feat(sql): add support for X in Y
fix(core): avoid NPE when Z
test(ilp): add regression test for issue #1234
Before opening a PR, please ensure:
-
Code is formatted as per the repo's settings (see Code formatting).
-
Tests pass locally; add/adjust tests for your changes.
-
No new third-party dependencies are introduced.
-
Commit messages follow Conventional Commits.
-
The PR description must include:
- Link to the relevant issue
- Clear explanation of why the change is needed
- Technical rationale and approach taken
- For performance-related changes: before/after benchmarks with data volumes
Reviewers should not have to reverse-engineer algorithms from code to understand what the PR does.
External contributors should contribute from forks of the repository. Internal
contributors (QuestDB team members) must prefix branch names with their initials
(e.g., jd/fix-parser-bug).
- Reviews begin once the PR is marked ready and CI passes
- We will not always remind contributors to check CI status; it is your responsibility to monitor your PR
- PRs that remain open for more than 2 weeks with failing CI will be closed
- Massive PRs from first-time contributors will be rejected — start with smaller, focused contributions to establish trust
Why does the server work, but the UI returns a 404 on localhost:9000?
This means that the web console artifacts are not present in
core/src/main/resources/io/questdb/site/public.zip. To fix this, you can
simply run:
mvn clean package -DskipTests -P build-web-consoleSome antivirus software may cause tests to fail. Typical indicators that antivirus is interfering with tests are that tests pass on CI but fail in the following cases:
- HTTP chunk size assertion (missing initial zeroes in e.g.
IODispatcherTest) - Test timeout
- JVM crash
In case of ESET products, the following steps may resolve the issue:
- Disable "application protocol content filtering" explicitly, or
- Add
127.0.0.1to the "Excluded IP addresses" list in the advanced settings menu because disabling all top-level mechanisms doesn't turn protocol filtering off.
We have an engineering project board to help us organize pending GitHub issues among engineers across different timezones. There are configured views for bug reports and feature requests respectively.
This is what you can do to organize open issues:
- Add new issues to the project board
- Always assign yourself when you pick up an issue
- Label the issues correctly after you assess them
- Close the issue when no further action is required
Stages of our project board:
| Stage | Description |
|---|---|
| New | When users report a bug; wait for someone to reproduce or follow up |
| More info needed | When more communication with OP is required before we can begin triage |
| To do | Once issues are confirmed and engineers can pick them up. Order of items should imply priority |
| In progress | If an engineer picks up an issue, self-assign and move the issue to In progress |
| Done | Once the linked pull request is merged, the issue is closed and moved to Done automatically |
We also use labels to organize GitHub issues to have better overview. The current labels can be roughly categorized as below:
| Categories | Labels |
|---|---|
| Type | Bug, New features, Enhancement, Test, Tidy up, Question, Performance, Java |
| Component | ILP, Rest API, Postgres wire, SQL, Core, UI |
| Priority | Immediate, Minor, Won't fix, Later |
| Difficulty | Good first issue |