Connect
ReifyDB is one engine with two deployment shapes: embedded inside your Rust process, or as a server that clients reach over WebSocket and HTTP. This page shows the shortest working connection from each supported surface, plus the default ports and how authentication works. The per-client pages under Clients go deeper.
No server yet? Use the browser
The fastest connection is no connection. The playground and every runnable snippet in these docs execute against a real ReifyDB engine compiled to WebAssembly, entirely in your browser. Nothing to install, nothing to configure. If you are evaluating RQL or the data model, start with the Quickstart and come back here when you want a database your application can talk to.
Endpoints and ports
The reifydb server binary (see Installation) listens on two application endpoints and keeps administration on separate, loopback-only listeners:
- --
ws://localhost:8091- WebSocket. One persistent connection for queries, commands, and live subscriptions. This is the default choice for applications. - --
http://localhost:8090- HTTP. Plain request/response. Right for serverless functions, scripts, and anywhere a long-lived socket is awkward. No subscriptions. - --Admin listeners on loopback:
127.0.0.1:9090(HTTP),127.0.0.1:9091(WebSocket), and127.0.0.1:9092(admin web UI).
The split exists because requests come in three kinds. A query reads, a command writes data, and an admin statement changes schema or identities. The application endpoints accept queries and commands only; admin statements are rejected there and must go through an admin listener. Frontends can face the public ports directly while CREATE TABLE and CREATE USER stay reachable only from the machine itself.
TypeScript / JavaScript
@reifydb/client works in Node.js and the browser:
npm install @reifydb/client @reifydb/coreConnect over WebSocket, run a query, disconnect. The third argument describes the result shape you expect back, so the rows arrive as typed objects:
import { Client } from '@reifydb/client';
import { Shape } from '@reifydb/core';
const client = await Client.connect_ws('ws://localhost:8091');
const frames = await client.query(
'MAP { answer: 42 }',
{},
[Shape.object({ answer: Shape.number() })],
);
console.log(frames[0][0].answer); // 42
client.disconnect();Client.connect_http('http://localhost:8090') gives you the same query and command methods over plain HTTP, without subscriptions. Both accept options like timeout_ms and token. Details, React hooks, and the in-browser WASM build live on the TypeScript client page.
Rust client
The reifydb-client crate talks to a server over WebSocket or HTTP:
use reifydb_client::{WireFormat, WsClient};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = WsClient::connect("ws://localhost:8091", WireFormat::Json).await?;
let frames = client.query("MAP { answer: 42 }", None).await?;
for frame in frames {
println!("{}", frame);
}
client.close().await?;
Ok(())
}HttpClient::connect("http://localhost:8090", WireFormat::Json) is the request/response equivalent. Subscriptions, batch subscriptions, and typed row extraction with FromFrame are covered on the Rust client page.
Rust embedded
If your application is Rust, you can skip the network entirely. The reifydb crate runs the whole engine in-process, the way you would embed SQLite:
use reifydb::{Params, embedded};
fn main() {
let db = embedded::memory().build().unwrap();
let frames = db.command_as_root("MAP { answer: 42 }", Params::None).unwrap();
for frame in frames {
println!("{}", frame);
}
}embedded::memory() keeps everything in memory; embedded::sqlite(config) persists to disk. There are no ports and no login: your process owns the engine, and the _as_root methods execute as the root identity. Sessions let you run work as other identities. See Rust (Embedded) for the builder options.
Python
A Python binding exists as an early-stage, embedded-only package: it runs the engine inside the Python process rather than connecting to a server. Expect its API to change. See the Python client page for current status.
Authentication
A fresh connection to the server runs as the anonymous identity. What anonymous is allowed to do is decided by policies, not by the transport, so an open port is not an open database. To act as a real user, the client logs in and receives a session token.
Users and their credentials are created with admin statements, so they go through an admin listener:
CREATE USER alice;
CREATE AUTHENTICATION FOR alice { method: password; password: 'alice-pass' };
CREATE USER bob;
CREATE AUTHENTICATION FOR bob { method: token; token: 'bob-secret-token' };Clients then authenticate with whichever method the user has. A successful login returns a session token; logout revokes it server-side:
const client = await Client.connect_ws('ws://localhost:8091');
const { token, identity } = await client.login_with_password('alice', 'alice-pass');
// or: await client.login_with_token('bob-secret-token');
// ... queries and commands now run as alice ...
await client.logout();To resume a session on a new connection, pass the token up front: Client.connect_ws(url, { token }). The Rust client mirrors this with login_with_password, login_with_token, and authenticate(token).
Choosing a connection
- --Rust application, single process owns the state: embedded. No network hop, no auth surface.
- --Frontends, services, or anything long-lived that wants live data: WebSocket on 8091. Unlike HTTP, it carries subscriptions.
- --Short-lived scripts, serverless functions, curl: HTTP on 8090.
- --Migrations, schema changes, user management: the admin listeners on loopback.
