kalam-client
Official Rust SDK for KalamDB — SQL, materialized live rows, and strong tenant isolation in one crate.
Status: Beta — the API surface is still evolving.
KalamDB is built for apps where every user or tenant owns a private data space. The same SQL can run for every signed-in customer, while USER tables ensure each query only touches that caller's data. On the server and in native SDKs, the default realtime API is live(): you receive the current materialized row set, not a stream of low-level diff frames that your UI has to reconcile.
→ kalamdb.org · Docs · GitHub
kalam-client provides:
- SQL execution over HTTP
- materialized live query rows over WebSocket with
live()andlive_with_config() - low-level realtime events with
live_events()when you need raw frames - per-user and per-tenant isolation with USER tables
- optional topic consumer workers behind the
consumerfeature - optional multipart file upload helpers behind the
file-uploadsfeature
Runtime targets:
- Tokio-based async Rust (
native-sdk, enabled by default) - WebAssembly builds for JavaScript bindings (
wasm, used by@kalamdb/client)
Installation
Add the crate from crates.io (or a path dependency while developing inside this repository):
[]
= "0.5"
= { = "1", = ["macros", "rt-multi-thread"] }
Enable optional capabilities with Cargo features:
# App-facing SQL + live rows (default)
= { = "0.5", = ["native-sdk"] }
# Topic workers and batch consumption
= { = "0.5", = ["native-sdk", "consumer"] }
# Multipart SQL file uploads
= { = "0.5", = ["native-sdk", "file-uploads"] }
| Feature | Description |
|---|---|
native-sdk (default) |
Tokio runtime, HTTP queries, auth flows, live subscriptions |
consumer |
TopicConsumer, ConsumerBuilder, consume/ack topic APIs |
file-uploads |
Multipart SQL upload helpers |
healthcheck |
Cached /v1/api/healthcheck helper |
setup |
First-run server setup helpers |
cluster |
Cluster health inspection |
wasm |
WASM bindings (used by the TypeScript SDK, not typical for Rust apps) |
Topic workers ship in the same crate behind consumer so app-only installs stay lean, matching how @kalamdb/consumer extends @kalamdb/client in TypeScript.
Why live() First
Most UIs do not want subscription_ack, initial_data_batch, change, and error frames. They want the latest rows.
live() gives you exactly that:
- the current row set already reconciled for insert, update, and delete
- one event shape for initial load and future changes
- shared behavior with the TypeScript and Dart clients
- simpler services, CLIs, and background workers
Use SubscriptionOptions::with_last_rows() when you want an initial rewind from the server. Use LiveRowsConfig { limit: Some(n), .. } when you want the client to keep the materialized live row set bounded over time.
The knobs apply at different layers:
batch_sizechunks the initial snapshot from the serverlast_rowschooses how much history to rewind firstlimitcaps the materialized live row set the client keeps afterward
Use live_events() only when you need the raw event protocol.
Quick Start
Start with a USER table. The SQL stays simple, and KalamDB scopes the data per authenticated user.
CREATE NAMESPACE IF NOT EXISTS support;
(
id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID,
room TEXT NOT NULL DEFAULT 'main',
role TEXT NOT NULL,
body TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW
) WITH (TYPE = 'USER');
use Duration;
use ;
use json;
async
See QUICKSTART.md for a shorter copy-paste flow and examples/ for runnable projects.
Resume From a Specific SeqId
When you want offline resume or a durable checkpoint, persist the last SeqId you applied and feed it back through SubscriptionOptions::with_from().
use ;
let start_from = from;
let options = new
.with_last_rows
.with_from;
Each LiveRowsEvent::Rows includes last_seq_id so you can persist checkpoints between sessions.
Lower-Level Realtime API
If you need raw protocol frames, use live_events().
use ;
let config =
new;
let mut events = client.live_events_with_config.await?;
while let Some = events.next.await
Use this API for protocol tooling, debugging, or custom reconciliation. For app UI state, prefer live().
Topics and Workers
Topic workers live behind the optional consumer feature so app-only installs keep the main SDK lean.
[]
= { = "0.5", = ["native-sdk", "consumer"] }
Use the default client surface for app-facing SQL, live rows, subscriptions, auth, and files. Enable consumer for TopicConsumer, ConsumerBuilder, consume_batch(), and ack().
use AutoOffsetReset;
let consumer = client
.consumer
.group_id
.topic
.auto_offset_reset
.build?;
See examples/topic-consumer for a fuller worker loop.
Authentication
AuthProvider is the canonical way to configure the client.
use AuthProvider;
// Static JWT
let auth = jwt_token;
// Basic auth (exchanged for JWT on first use)
let auth = basic_auth;
// Local root / system user
let auth = system_user_auth;
The SDK handles:
- Basic-auth-to-JWT exchange
- default namespace forwarding for
/v1/api/sqlplus unqualified live/file contexts - shared WebSocket connection management
- reconnect controls and
SeqIdtracking
Examples and Tests
| Crate | What it shows |
|---|---|
| examples/quickstart | Connect, run SELECT CURRENT_USER(), disconnect |
| examples/live-inbox | USER table + materialized live() loop |
| examples/topic-consumer | consumer feature + TopicConsumer |
tests/*.rs |
Offline API guards plus server-backed integration tests |
Run the SDK test suite from this directory:
NO_SERVER=true
From the repo root:
Set KALAMDB_SERVER_URL (default http://localhost:2900) and credentials as needed.
API Pointers
execute_query()and related SQL helpers for reads and writeslive()andlive_with_config()for materialized realtime rowslive_events()andlive_events_with_config()for low-level subscription framesTopicConsumerandclient.consumer()(featureconsumer) for topic consumption and commits
Full docs: kalamdb.org/docs/sdk/rust
Issues: github.com/kalamdb/KalamDB/issues
For crate development, publishing, and contribution details, see DEV.md.
License
Licensed under the Apache License, Version 2.0 (Apache-2.0). See LICENSE.