Expand description
§QuestDB Client Library for Rust
Official Rust client for QuestDB, an open-source SQL database designed to process time-series data, faster.
The client library is designed for fast ingestion of data into QuestDB, and for querying it back out.
Its centrepiece is the QuestDB Wire Protocol (QWP) over WebSocket:
QuestDB’s native binary columnar protocol, covering both directions. Writes
are acknowledged per flush and go through QuestDb — a thread-safe
connection pool with automatic reconnect — as rows, columns, Apache Arrow
RecordBatches or Polars DataFrames.
Multi-endpoint failover requires QuestDB Enterprise. Queries stream result
sets back over the same protocol as columnar batches, RecordBatches or
DataFrames.
The InfluxDB Line Protocol (ILP) over HTTP or TCP, and QWP over UDP, are also supported for ingestion.
Version 7.0.0 requires Rust 1.91.1. QWP over WebSocket requires QuestDB 10.0 or newer.
§Transports
The transport is selected by the scheme in the configuration string:
ws::addr=.../wss::addr=...(alsows::/wss::) — QWP over WebSocket, in both directions. For ingestion (QuestDb::connect): binary columnar frames with per-flush acknowledgements, a thread-safe connection pool with automatic reconnect, and row, column, ArrowRecordBatchand PolarsDataFrameinput. Multi-endpoint failover requires QuestDB Enterprise. For queries (Reader::from_conforQuestDb::borrow_reader): SQL execution with results streamed back as columnar batches. Requires QuestDB 10.0+.http::addr=.../https::addr=...— ILP request-response, errors returned to the client, supports authentication and TLS.tcp::addr=.../tcps::addr=...— ILP streaming, legacy; errors cause server-side disconnect and surface only in server logs.udp::addr=...— best-effort UDP datagrams (IPv4-only); no acknowledgements, no authentication, no TLS, no transactional guarantees. See theingressmodule docs (in particularProtocol::Udp) for semantics and configuration parameters.
§ILP Protocol Versions
The library supports the following ILP protocol versions. These apply to ILP/HTTP and ILP/TCP only — QWP uses its own wire format and is not versioned through this mechanism.
- If you use HTTP and
protocol_version=autoor unset, the library will automatically detect the server’s latest supported protocol version and use it (recommended). - If you use TCP, you can specify the
protocol_version=Nparameter when constructing theSenderobject (TCP defaults toprotocol_version=1).
| Version | Description | Server Compatibility |
|---|---|---|
| 1 | Over HTTP it’s compatible with InfluxDB Line Protocol (ILP) | All QuestDB versions |
| 2 | 64-bit floats sent as binary, adds n-dimensional arrays | 9.0.0+ (2025-07-11) |
Note: QuestDB server version 9.0.0 or later is required for protocol_version=2 support.
§Quick Start
To start using questdb-rs, add it as a dependency of your project:
cargo add questdb-rs§QWP: the QuestDb connection pool
QuestDb is the entry point for QWP/WebSocket (QuestDB 10.0+): one
thread-safe pool covering both writes and reads. A Polars round trip (with
the polars feature):
use questdb::{QuestDb, ingress::polars::PolarsIngestOptions};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let db = QuestDb::connect("ws::addr=localhost:9000;")?;
// One call: stream the DataFrame in columnar batches, wait for the ack.
db.flush_polars_dataframe("trades", &df, &PolarsIngestOptions::new())?;
// Query it back over the same pool.
let back = db
.borrow_reader()?
.execute("SELECT * FROM trades WHERE amount > 0.001")?
.fetch_all_polars()?;
println!("{back}");
Ok(())
}The pool’s main handles:
db.flush_polars_dataframe(table, &df, &options)— one-callDataFrameingestion (polarsfeature).db.flush_arrow_batch(table, &batch, ts_column, overrides, ack)— one-call ArrowRecordBatchingestion (arrowfeature).db.borrow_sender()— unified ingestion: publish row-builtBufferpayloads (table(..).symbol(..).column_f64(..).at(..)) or fill and reuse a columnarChunk; the same lease also accepts Arrow batches.db.borrow_reader()— run SQL and stream the result set back.
Handles return to the pool on drop, and the pool reconnects to the configured
endpoint transparently. With QuestDB Enterprise it also fails over across
addr=host-a:9000,host-b:9000 endpoint lists.
To keep the ingest publication log across reconnects and producer-process
restarts, configure sf_dir. Its default sf_durability=memory mode relies on
the OS page cache and does not protect against host power loss. Periodic
durability adds background disk checkpoints:
ws::addr=localhost:9000;sf_dir=/var/lib/my-app/questdb-sf;sender_id=orders;sf_durability=periodic;sf_sync_interval_millis=5000;The interval defaults to 5000 ms in periodic mode and is a target cadence:
runner scheduling and storage-sync latency add to the actual recovery window.
Publication can see ordinary backpressure at a segment boundary until the
segment has been checkpointed. This local durability is independent of the
QuestDB Enterprise server barrier selected by request_durable_ack=on; use
both when end-to-end durability is required.
A standalone Reader::from_conf("ws::addr=...") gives the query side
without a pool (sync-reader-qwp-ws feature), yielding results as native
columnar batches, Arrow RecordBatches (cursor.next_arrow_batch()) or
Polars DataFrames (cursor.fetch_all_polars()).
§ILP over HTTP
use questdb::{
Result,
ingress::{
Sender,
Buffer,
TimestampNanos}};
fn main() -> Result<()> {
let mut sender = Sender::from_conf("http::addr=localhost:9000;")?;
let mut buffer = sender.new_buffer();
buffer
.table("trades")?
.symbol("symbol", "ETH-USD")?
.symbol("side", "sell")?
.column_f64("price", 2615.54)?
.column_f64("amount", 0.00044)?
// Array ingestion (QuestDB 9.0.0+). Slices and ndarray supported through trait
.column_arr("price_history", &[2615.54f64, 2615.10, 2614.80])?
.column_arr("volatility", &ndarray::arr1(&[0.012f64, 0.011, 0.013]).view())?
.at(TimestampNanos::now())?;
sender.flush(&mut buffer)?;
Ok(())
}§Docs
Use the QuestDB Rust client guide
for task-oriented documentation. The exact API contract is on docs.rs: start
with QuestDb,
then see the
ingress and
egress modules.
§Examples
A selection of usage examples is available in the examples directory:
| Example | Description |
|---|---|
basic.rs | Minimal TCP ingestion example; shows basic row and array ingestion. |
auth.rs | Adds authentication (user/password, token) to basic ingestion. |
auth_tls.rs | Like auth.rs, but uses TLS for encrypted TCP connections. |
from_conf.rs | Configures client via connection string instead of builder pattern. |
from_env.rs | Reads config from QDB_CLIENT_CONF environment variable. |
http.rs | Uses HTTP transport and demonstrates array ingestion with ndarray. |
protocol_version.rs | Shows protocol version selection and feature differences (e.g. arrays). |
qwp_ws_chunk_and_query.rs | Shares one QuestDb pool between concurrent columnar ingestion and query workers. |
qwp_ws_l1_quotes.rs | Columnar ingestion over QWP/WebSocket via the QuestDb connection pool. |
qwp_egress_read.rs | Runs a SQL query and streams the result set over QWP/WebSocket. |
polars.rs | Round trip: ingests a Polars DataFrame and queries it back as one. |
§Crate features
The crate provides several optional features to enable additional functionality. You can enable features using Cargo’s --features flag or in your Cargo.toml.
§Default features
- sync-sender: Enables
sync-sender-tcp,sync-sender-httpandsync-sender-qwp-ws(ingestion). - sync-reader: Enables
sync-reader-qwp-wsandsync-reader-zstd(queries). Querying is first-class, on by default. - sync-sender-tcp: Enables ILP/TCP (legacy). Depends on the
socket2crate. - sync-sender-http: Enables ILP/HTTP support. Depends on the
ureqcrate. - sync-sender-qwp-ws: Enables unified QWP/WebSocket ingestion through the
QuestDbpool. - sync-reader-qwp-ws: Enables QWP/WebSocket queries (
Reader/Cursor). - sync-reader-zstd: Enables zstd decompression of query result batches.
- tls-webpki-certs: Uses a snapshot of the Common CA Database as root TLS certificates. Depends on the
webpki-rootscrate. - ring-crypto: Uses the
ringcrate as the cryptography backend for TLS (default crypto backend).
§Optional features
-
arrow: Apache Arrow integration in both directions — ingest
RecordBatches, read query results asRecordBatches. Also available as the single-directionarrow-ingress/arrow-egressfeatures. -
polars: Polars integration in both directions — ingest
DataFrames, read query results asDataFrames. Also available aspolars-ingress/polars-egress. -
chrono-timestamp: Allows specifying timestamps as
chrono::DateTimeobjects. Depends on thechronocrate. -
tls-native-certs: Uses OS-provided root TLS certificates for secure connections. Depends on the
rustls-native-certscrate. -
insecure-skip-verify: Allows skipping verification of insecure certificates (not recommended for production).
-
ndarray: Enables integration with the
ndarraycrate for working with n-dimensional arrays. Without this feature, you can still send slices or implement custom array types via theNdArrayViewtrait. -
aws-lc-crypto: Uses
aws-lc-rsas the cryptography backend for TLS. Mutually exclusive with thering-cryptofeature. -
almost-all-features: Convenience feature for development and testing. Enables most features except mutually exclusive crypto backends.
See the
Cargo.tomlfor the full list and details on feature interactions.
§C, C++ and Python APIs
This crate is also exposed as a C and C++ API and in turn exposed to Python.
- This project’s GitHub page for the C and C++ API.
- Python bindings.
§Community
If you need help, have additional questions or want to provide feedback, you may find us on Slack.
You can also sign up to our mailing list to get notified of new releases.
Modules§
- arrow_
metadata - Transport-neutral Arrow field-metadata keys, shared by both the ingress
Arrow encoder (
RecordBatch→Buffer) and the egress Arrow adapter (Cursor→RecordBatch). Lives here — rather than underegress::arrow— so a sender-onlyarrow-ingressbuild can reference the keys without pulling in the egress reader. This top-level module is the canonical public home for metadata used by either direction. - egress
- QuestDB Wire Protocol (QWP) egress reader.
- ingress
- Fast Ingestion of Data into QuestDB
Structs§
- Borrowed
Reader - A query
Readerborrowed from aQuestDbpool. - Borrowed
Sender - Store-and-forward QWP sender borrowed from a
QuestDbpool — the handle returned byQuestDb::borrow_sender. - Connect
Handlers - Connection pool for QWP/WebSocket ingestion and egress.
- Error
- An error that occurred when using the QuestDB client library.
- QuestDb
Enums§
- Error
Code - Category of error.