QuestDB - Client Library for Rust, C and C++
This library inserts data into QuestDB and queries it back out.
The primary protocol is the QuestDB Wire Protocol (QWP) over WebSocket,
QuestDB's native binary columnar format, used for both ingestion and queries.
QWP traffic runs over a thread-safe connection pool (QuestDb in Rust,
questdb_db in C/C++) with per-flush acknowledgements and automatic reconnect.
Multi-endpoint failover requires QuestDB Enterprise. You send rows, columns,
Apache Arrow record batches or Polars DataFrames (Rust); SQL results stream
back over the same pool in the same formats. QWP over WebSocket requires
QuestDB 10.0 or newer.
QWP also has a best-effort UDP transport for low-latency ingestion on trusted networks (batching is MTU-bounded).
- Written in Rust, with no additional run-time or link-time dependencies on the C++ standard library or other libraries.
- Ships as a static and a dynamic library.
- Exposes Rust, C11 and C++17 APIs; the C++ API is a header-only wrapper over the C API.
- Python bindings are available separately.
The Rust and native clients require Rust 1.91.1 to build. The C and C++ surfaces target C11 and C++17, with CMake 3.15 or newer. See the compatibility matrix for server, toolchain, platform, Arrow, and Polars support.
QWP/WebSocket is the main path, covered below. For cross-language code and production configuration, see the client documentation. QuestDB also accepts CSV uploads and PostgreSQL-wire inserts.
Legacy ILP transports (InfluxDB compatibility)
For InfluxDB-compatible ingestion the library still supports the legacy ILP
transports: ILP/HTTP (request-response; server errors returned to the
client; auth and TLS) and ILP/TCP (streaming; errors cause disconnect and
surface only in server logs). Over HTTP the protocol version is auto-detected;
over TCP it defaults to version 1 (InfluxDB-compatible) and can be raised with
protocol_version=N.
See the flush troubleshooting docs for debugging ILP/TCP disconnects, and the ILP protocol reference for the wire format.
One pool handle covers both directions. In Rust:
let db = QuestDb::connect("ws::addr=localhost:9000;")?;
// Write: one call streams the whole DataFrame and waits for the ack.
db.flush_polars_dataframe("trades", &df, &PolarsIngestOptions::new())?;
// Read: borrow a reader from the same pool, run SQL, stream the result.
let back = db
.borrow_reader()?
.execute("SELECT * FROM trades WHERE amount > 0.001")?
.fetch_all_polars()?;Besides flush_polars_dataframe and flush_arrow_batch, the pool hands out
borrow_sender() for both row-built Buffer payloads and columnar Chunk /
Arrow payloads, plus borrow_reader() for SQL queries. Handles return to the
pool on drop. Reader::from_conf runs queries without a pool, yielding native
columnar batches, Arrow RecordBatches or Polars DataFrames.
The C and C++ APIs expose the pool via
questdb/client.h /
questdb/client.hpp (questdb_db_connect,
questdb::pool), and the leases borrowed from it via
questdb/ingress/qwp_sender.h
(questdb_db_borrow_sender) and
questdb/egress/qwp_reader.h /
questdb/egress/qwp_reader.hpp
(questdb_db_borrow_reader), handing data across the Arrow C Data Interface.
Each lease header includes the pool header, so a one-direction consumer
includes only the header for that direction. In Rust, QWP ingestion
(sync-sender-qwp-ws) and queries (sync-reader-qwp-ws) are both on by
default; Arrow and Polars conversions sit behind the arrow and polars
features.
Read the language-specific guides:
C
- Getting started with C
- Shared-pool ingestion and query example
.hheader file (the pool).hheader file (ingestion).hheader file (queries)
C++
- Getting started with C++
- Shared-pool ingestion and query example
.hppheader file (the pool).hppheader file (ingestion).hppheader file (queries)
Rust
- Getting started with Rust
questdb-rscrate on crates.io- API docs on docs.rs
questdb-rssource codequestdb-rs-ffisource code - C bindings code
Python
- Documentation index
- Data quality and threading considerations
- Authentication and TLS encryption
- QWP ingress and egress soak harness
Questions or feedback? Reach us on the Community Forum. To hear about new releases, sign up to the mailing list.
The code is released under the Apache License.