Configuration Guide¶
BenoStreamDB is designed to be highly configurable through environment variables, runtime options, and a centralized configuration file.
Environment Variables¶
Core Engine & Memory Management¶
Variable |
Description |
Default |
|---|---|---|
|
Memory limit for vector (HNSW-IVF), inverted, and byte caches in GB. |
|
|
Memory limit for decoded RecordBatch Hot Row Cache in GB. |
|
|
Local disk directory used for caching remote index files. |
|
|
Local directory for the layered-index cache when reading external (REST-catalog) tables. |
|
|
Default table/storage URI for the gateway and Iceberg REST binaries. |
|
|
Path to a centralized |
None |
|
Maximum concurrent segment reader threads per query. |
Auto (min(cores, 64)) |
|
Global Rayon worker pool thread count for parallel index construction. |
Auto (50% of CPU cores) |
|
DataFusion query memory limit in GB; SQL sorts/joins spill to disk past it. |
Half the effective memory budget |
|
DataFusion target partition count for query execution. |
Effective CPU budget (respects cgroup limits) |
|
Maximum concurrent background index builds. Non-positive values are ignored. |
One build per ~8 GB RAM, capped at CPU count, min 1 |
|
Refuse a local flush that would drop free disk below this many GB. |
|
Concurrency Tuning: BSDB_MAX_CONCURRENCY vs RAYON_NUM_THREADS¶
BSDB_MAX_CONCURRENCY and RAYON_NUM_THREADS operate on different execution layers and should generally not be set to the same value:
RAYON_NUM_THREADS(CPU-Bound Data Parallelism):Governs Rayon’s worker threadpool for compute-intensive tasks: AVX-512/NEON SIMD vector distance calculations, HNSW graph construction and deserialization, and Product Quantization (PQ) training.
Rule: Keep $\le$ physical CPU cores (typically
cores / 2orcores - 1). Setting it higher causes OS thread context switching and CPU cache thrashing.
BSDB_MAX_CONCURRENCY(I/O-Bound Async Stream Concurrency):Governs Tokio async task concurrency for opening and streaming Parquet segments from local disk or remote object storage (
s3://,gs://).Non-blocking I/O tasks spend most of their time awaiting network packets or disk blocks without consuming CPU.
Rule: Can be $2\times$ to $4\times$ CPU cores (e.g. 8–32) for fast parallel segment fetching, bounded only by RAM memory buffer headroom.
Sizing & Tuning Matrix¶
Deployment Profile |
Machine Specs |
|
|
Notes |
|---|---|---|---|---|
Benchmark / Container |
4 Cores, 4 GB RAM |
|
|
Stable profile used in 100k & 1M OpenSearch benchmark. |
Production Server |
16 Cores, 32 GB RAM |
|
|
High throughput for mixed scalar + vector queries. |
Cloud Object Store (S3/GCS) |
8 Cores, 32 GB RAM |
|
|
High I/O concurrency hides cloud object storage latency. |
Security¶
Authentication (search gateway + Flight SQL)¶
Stateless auth — no user database. Identity is delegated to a shared secret or an external IdP’s signing key. The same credentials protect the OpenSearch/ES API, the Qdrant API, and the Flight SQL gRPC service.
Variable |
Description |
Default |
|---|---|---|
|
Shared secret. HTTP: |
unset |
|
HS256 shared secret for JWT verification. |
unset |
|
RS256 public key (PEM) for JWT verification — the “delegate to your IdP” path. |
unset |
|
Required |
unset |
|
Required |
unset |
|
Fail closed ( |
|
|
Exempt |
|
Keep the secret in a secret manager (Vault, AWS/GCP/Azure Secrets Manager) or a
0600 file mounted at /run/secrets/ (Docker/K8s) or
/etc/benostreamdb/secrets/, loaded via systemd LoadCredential= /
EnvironmentFile= (mode 0600). Never commit it or place it in a
world-readable env file.
SSRF guard¶
Variable |
Description |
Default |
|---|---|---|
|
Enable the SSRF guard. When set to |
off |
Embeddings¶
Embedding provenance is a core table property (benostream.embedding.*, see the main README’s
“Embedding Provenance” section). These variables configure the embedding generator used by the MCP
server and the Python helpers.
Variable |
Description |
Default |
|---|---|---|
|
|
off (schema checks only) |
|
|
|
|
Hugging Face BERT-family model id that publishes |
|
|
Private model cache; reused after the first download. |
|
|
Ollama / OpenAI-compatible / TEI embedding endpoint. |
None |
|
Bearer token for the HTTP endpoint. |
None |
|
Candle inference batch size. |
|
|
Tokenizer truncation length. |
|
|
Optional dimension override for MRL truncation. Known models supply it from the id map, and loaded models supply it from |
Model default |
|
Override the query instruction prefix. Empty string disables it. |
Model default |
|
Override the document instruction prefix. Empty string disables it. |
Model default |
The Candle loader runs on CPU in the published build. The legacy model_path, device,
quantized, intra_threads, pooling, and show_download_progress JSON keys are accepted for
backward compatibility but ignored.
Write-Ahead Log (WAL) & Ingestion¶
Variable |
Description |
Default |
|---|---|---|
|
Directory for the Write-Ahead Log (WAL) used for streaming recovery. |
|
|
WAL flush durability policy ( |
|
|
File size threshold in MB before triggering WAL log segment compaction. |
|
|
Appended operations batch size before triggering a WAL sync flush. |
|
|
Maximum elapsed milliseconds between background WAL sync flushes. |
|
|
Background timer interval in seconds to automatically flush write buffers to Iceberg snapshots. |
None |
|
Ingest RAM high-water mark in GB; writers pause above it (with a fail-open grace) until background tasks reclaim memory. |
80% of available memory |
|
Heap-trim budget during bulk ingest: RSS above it triggers |
80% of available memory |
|
Fail-open grace before a stalled writer proceeds anyway. Non-positive or unparseable values fall back to the default. |
|
|
Manifest files accumulated by the append-only fast path before a full consolidation commit. |
|
|
Minimum age before vacuum deletes an unreferenced file. |
|
|
Compatibility alias for |
|
Vector Index & GPU¶
Variable |
Description |
Default |
|---|---|---|
|
Device or comma-separated pool for vector index builds and distance kernels: |
unset ( |
|
HNSW per-node neighbour count. |
|
|
HNSW build beam width. |
|
|
IVF list count. |
Heuristic from vector count |
|
PRNG seed for k-means centroid initialization during IVF index building. Set to an integer to override the deterministic default seed ( |
|
|
PRNG seed for HNSW layer level assignment during graph building. |
unset (thread-local randomness) |
|
NVRTC library file or directory used to compile GPU kernels. |
Auto-discovery (CUDA home, Python site-packages, |
|
In-memory budget for graph-algorithm UDAF accumulators before they spill to the CSR index. |
Engine memory budget |
Catalog¶
Variable |
Description |
Default |
|---|---|---|
|
Catalog implementation: |
Inferred from the URI scheme or |
|
Catalog endpoint. |
None |
|
Warehouse / catalog name to register. |
None |
|
Default namespace for unqualified tables. |
None |
|
Vendor credential ( |
None |
|
Bearer token for catalog requests. |
None |
See Catalog Usage and benostream.toml below for the full
catalog configuration surface.
MCP Server (benostreamdb-mcp)¶
Variable |
Description |
Default |
|---|---|---|
|
Local warehouse path exposed to the agent. |
System temp dir |
|
Comma-separated or JSON array of schemas that allow writes. |
|
|
Comma-separated or JSON array of schemas locked read-only. |
|
|
Schema for unqualified table creation. |
|
|
Use a temporary warehouse for this session ( |
|
|
Full JSON configuration string. |
None |
|
Embedding generator settings (see Embeddings). |
See above |
See contrib/benostreamdb-mcp/README.md
for the full CLI/JSON mapping.
Search Gateway (benostreamdb-search)¶
The OpenSearch/Qdrant gateway is a separate component with its own
configuration surface (BSDB_SEARCH_*, BSDB_QDRANT_BIND, BSDB_QDRANT_PORT).
See the
search gateway README
for the full table.
Server binaries¶
The Flight SQL server (benostreamdb-flight) has its own variables:
Variable |
Description |
Default |
|---|---|---|
|
gRPC bind address. |
|
|
gRPC port. |
|
|
Row cap applied to Arrow Flight results. |
|
|
Refuse DDL, DML, and ingest. Set to |
off |
|
Warehouse root for the server. |
|
|
Catalog name to expose. |
From |
See the Flight SQL README.
Cloud Storage & Telemetry¶
Variable |
Description |
Default |
|---|---|---|
|
Custom S3 endpoint URL (used for RustFS, LocalStack, Ceph). |
AWS default |
|
Enable distributed OpenTelemetry tracing via Jaeger / OTLP. |
|
|
Bind address for the embedded/Flight metrics HTTP listener. |
|
|
Port for the embedded/Flight metrics HTTP listener. |
|
|
Exempt |
|
|
OTLP/HTTP metrics endpoint (e.g. |
None |
|
Comma-separated |
None |
|
OTLP push period in seconds. |
|
|
|
|
Development, Test & Benchmark Variables¶
These are not engine runtime settings. They are read by scripts, tests, or packaging workflows in this repository.
Variable |
Used by |
Description |
|---|---|---|
|
|
Allow the CSR benchmark to run against a debug build ( |
|
|
Degree cap for the generated subgraph. |
|
|
Input directory for downloaded Wikipedia/demo dumps. |
|
|
Index type selected by the competitor benchmark harness ( |
|
|
Output table directory. |
|
|
Root output directory for the three-tier build. |
|
|
Rows per embedding shard. |
|
|
Rows per load chunk. |
|
|
Demo database path for the Streamlit/Dash UIs. |
|
|
Internal guard that stops the GPU-probe child from recursing. |
|
|
RSS ceiling for the soak test (default 8 GiB). |
|
S3 multi-writer tests |
Bucket used by the concurrency tests. |
|
randomized workload tests |
LCG seed (default |
|
randomized workload tests |
Number of randomized steps (default |
|
release workflow / dbt adapter |
Forced version string for packaging. |
|
|
Image tag for the search/Flight containers ( |
See Monitoring & Operations for the full metric catalog and the per-deployment-mode endpoints.
The benostream.toml File¶
You can use a TOML file to manage complex configurations, especially for catalogs and multi-cloud storage.
BenoStreamDB looks for this file in the following order:
Environment variable
BSDB_CONFIG./benostream.toml(current directory)~/.benostream/config.toml
Example Configuration¶
[storage]
type = "s3"
bucket = "my-data-lake"
region = "us-east-1"
endpoint = "http://rustfs:9000"
[cache]
memory_limit_gb = 8
block_cache_gb = 8
disk_cache_enabled = true
disk_cache_path = "/mnt/fast-ssd/hdb_cache"
[wal]
durability = "adaptive"
[catalog]
type = "rest"
url = "https://polaris.example.com/api/catalog/v1"
warehouse = "main_warehouse"
credential = "CLIENT_ID:CLIENT_SECRET"
scope = "PRINCIPAL_ROLE:ALL"
token_refresh_interval_secs = 300
Storage Credentials¶
BenoStreamDB uses the standard object-store crate, which automatically picks up credentials from:
AWS:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGION, or IAM Roles.GCP:
GOOGLE_APPLICATION_CREDENTIALS(JSON key file path).Azure:
AZURE_STORAGE_ACCOUNT,AZURE_STORAGE_KEY.
Query Configuration (QueryConfig)¶
Query-level options are set via the QueryConfig struct (Rust). The Python binding exposes the same SQL execution surface through Table.sql() and Session.sql().
Option |
Description |
Default |
|---|---|---|
|
Maximum duration before a query is cancelled. Set to |
|
|
Hard cap on rows returned. Prevents unbounded result sets from exhausting memory. |
|
|
Maximum parallel segment readers. Capped at 64 to prevent oversubscription. |
Auto-detected ( |
Python Example¶
import benostreamdb as bsdb
table = bsdb.Table("s3://bucket/my-table")
# The table is registered as 't' for the duration of the query
results = table.sql(
"SELECT * FROM t WHERE embedding <-> '[0.1, 0.2]'::vector"
)
Query timeouts, result-row caps, and reader concurrency are
QueryConfigfields on the Rust surface; they are not keyword arguments on the PythonTable.sql()method.
Rust Example¶
use benostreamdb::{Table, QueryConfig};
let table = Table::new("s3://bucket/my-table")?;
let config = QueryConfig::default()
.query_timeout_secs(30)
.max_result_rows(100_000);
let batches = table.query_with_config("SELECT * FROM documents", config).await?;
Vector index configuration¶
(merged from the former CONFIGURATION.md)
This guide covers configuration parameters for tuning vector search performance in BenoStreamDB.
Configuration Parameters¶
HNSW Parameters¶
ef_search¶
Controls the search beam width for HNSW index queries.
Type: Integer
Default: 64
Range: 1 - 1000
Effect: Higher values increase accuracy but reduce speed
Usage (optimizer hint):
SELECT /*+ INDEX_HINT(ef_search=128) */
id, embedding <-> '[0.1, 0.2, 0.3]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;
Python API (per-query vector filter):
import benostreamdb as bsdb
table = bsdb.Table("s3://bucket/documents")
results = table.to_pandas(
vector_filter={
"column": "embedding",
"query": [0.1, 0.2, 0.3],
"k": 10,
"ef_search": 128,
}
)
Performance Impact:
ef_search = 32: Fast, ~90% recallef_search = 64: Balanced, ~95% recall (default)ef_search = 128: Accurate, ~98% recallef_search = 256: Very accurate, ~99.5% recall
IVF Parameters¶
probes¶
Controls the number of IVF clusters to search.
Type: Integer
Default: 10
Range: 1 - 1000
Effect: Higher values increase accuracy but reduce speed
Usage (optimizer hint):
SELECT /*+ INDEX_HINT(probes=20) */
id, embedding <-> '[0.1, 0.2, 0.3]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;
Python API (per-query vector filter):
import benostreamdb as bsdb
table = bsdb.Table("s3://bucket/documents")
results = table.to_pandas(
vector_filter={
"column": "embedding",
"query": [0.1, 0.2, 0.3],
"k": 10,
"probes": 20,
}
)
Performance Impact:
probes = 5: Fast, ~85% recallprobes = 10: Balanced, ~92% recall (default)probes = 20: Accurate, ~97% recallprobes = 50: Very accurate, ~99% recall
Index Control¶
use_index¶
Controls whether to use vector indexes or force sequential scan.
Type: Boolean
Default: true
Effect: When false, forces sequential scan (useful for testing)
Usage (optimizer hint):
-- Force a sequential scan (for testing)
SELECT /*+ INDEX_HINT(use_index=false) */
id, embedding <-> '[0.1, 0.2, 0.3]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;
Tuning Guidelines¶
Accuracy vs Speed Tradeoff¶
Use Case |
ef_search |
probes |
Expected Recall |
Relative Speed |
|---|---|---|---|---|
Real-time search |
32 |
5 |
~88% |
4x faster |
Balanced |
64 |
10 |
~94% |
1x (baseline) |
High accuracy |
128 |
20 |
~98% |
0.5x slower |
Maximum accuracy |
256 |
50 |
~99.5% |
0.2x slower |
Dataset Size Recommendations¶
Small datasets (< 100K vectors):
SELECT /*+ INDEX_HINT(ef_search=128, probes=20) */
id, embedding <-> '[0.1, 0.2, 0.3]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;
Medium datasets (100K - 10M vectors):
SELECT /*+ INDEX_HINT(ef_search=64, probes=10) */ ... -- defaults
Large datasets (> 10M vectors):
SELECT /*+ INDEX_HINT(ef_search=32, probes=5) */ ...
Dimensionality Recommendations¶
Low dimensions (< 128):
SELECT /*+ INDEX_HINT(ef_search=64, probes=10) */ ...
Medium dimensions (128 - 768):
SELECT /*+ INDEX_HINT(ef_search=64, probes=10) */ ...
High dimensions (> 768):
SELECT /*+ INDEX_HINT(ef_search=128, probes=20) */ ...
Benchmarking¶
Measuring Recall¶
import benostreamdb as bsdb
import numpy as np
table = bsdb.Table("s3://bucket/documents")
query_vector = [0.1, 0.2, 0.3]
# High-recall reference run (wide beam)
reference = table.to_pandas(
vector_filter={
"column": "embedding",
"query": query_vector,
"k": 100,
"ef_search": 512,
}
)
reference_ids = set(reference["id"])
# Run under test (default beam)
results = table.to_pandas(
vector_filter={
"column": "embedding",
"query": query_vector,
"k": 100,
"ef_search": 64,
}
)
result_ids = set(results["id"])
# Calculate recall
recall = len(reference_ids & result_ids) / len(reference_ids)
print(f"Recall@100: {recall:.2%}")
Measuring Latency¶
import time
import numpy as np
import benostreamdb as bsdb
table = bsdb.Table("s3://bucket/documents")
vector_filter = {
"column": "embedding",
"query": [0.1, 0.2, 0.3],
"k": 10,
"ef_search": 64,
}
# Warmup
for _ in range(10):
table.to_pandas(vector_filter=vector_filter)
# Measure
latencies = []
for _ in range(100):
start = time.time()
table.to_pandas(vector_filter=vector_filter)
latencies.append(time.time() - start)
print(f"P50: {np.percentile(latencies, 50)*1000:.2f}ms")
print(f"P95: {np.percentile(latencies, 95)*1000:.2f}ms")
print(f"P99: {np.percentile(latencies, 99)*1000:.2f}ms")
Advanced Configuration¶
Per-Query Configuration¶
Per-query vector-search hints are supported via SQL comments:
-- Supported: INDEX_HINT(ef_search=..., probes=...)
SELECT /*+ INDEX_HINT(ef_search=128, probes=20) */
id, embedding <-> '[0.1, 0.2, 0.3]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;
Index build parameters are set during index creation using the fluent add_index method:
import benostreamdb as bsdb
table = bsdb.Table("s3://bucket/my-table")
# TurboQuant 8-bit quantization (Recommended Default)
# 4x compression, near-lossless accuracy
table.add_index("embedding", "hnsw_tq8")
# TurboQuant 4-bit quantization
# 8x compression, maximum efficiency
table.add_index("embedding", "hnsw_tq4")
# Custom HNSW parameters
table.add_index(
"embedding",
{
"type": "hnsw",
"complexity": 16, # Max connections per node (formerly 'm')
"quality": 200, # Construction beam width (formerly 'ef_construction')
}
)
# Product Quantization (PQ)
table.add_index(
"embedding",
{
"type": "hnsw_pq",
"compression": 32 # PQ subspaces (formerly 'subspaces')
}
)
Troubleshooting¶
Slow Queries¶
Symptom: Queries taking longer than expected
Solutions:
Reduce
ef_searchorprobesfor faster (but less accurate) resultsCheck if index exists:
SHOW INDEXES FROM table_nameVerify index is being used: Check query plan
Consider using binary vectors for 32x speedup
Low Recall¶
Symptom: Missing relevant results
Solutions:
Increase
ef_searchorprobesVerify index quality: Rebuild if necessary
Check vector normalization (for cosine distance)
Ensure query vector has same preprocessing as indexed vectors
Out of Memory¶
Symptom: OOM errors during queries
Solutions:
Reduce
ef_searchto lower memory usageUse binary vectors for 32x memory reduction
Use sparse vectors for high-dimensional sparse data
Increase available memory
Best Practices¶
Start with defaults: Use default parameters (ef_search=64, probes=10) initially
Measure first: Benchmark recall and latency before tuning
Tune incrementally: Adjust one parameter at a time
Monitor production: Track recall and latency metrics in production
Document settings: Record configuration choices for reproducibility
Configuration Reference¶
Hint key |
Type |
Default |
Range |
Description |
|---|---|---|---|---|
|
Integer |
64 |
1-1000 |
HNSW search beam width |
|
Integer |
10 |
1-1000 |
IVF clusters to search |
|
Boolean |
true |
true/false |
Enable/disable index usage |