VeltrixDB Docs
v1.1.0 GitHub FAQ Quickstart

Node.js Client

The Node.js client is a fully async, Promise-based driver built on the built-in net/tls modules — no third-party dependencies — with a single-connection client and an async connection pool.

Install

bash
npm install veltrixdb-client

Requires Node.js 16+.

Quick start

Taken from the SDK's example.js:

javascript
const { VeltrixDBClient } = require('veltrixdb-client'); async function main() { const c = new VeltrixDBClient({ host: '127.0.0.1', port: 9000 }); await c.connect(); await c.ping(); console.log('Connected to VeltrixDB'); // Put / Get / Delete await c.put('hello', Buffer.from('world')); const val = await c.get('hello'); console.log(`PUT+GET hello = ${val.toString()}`); await c.delete('hello'); const gone = await c.get('hello'); console.log(`GET after DEL hello = ${gone}`); // null c.close(); } main().catch(err => { console.error(`Error: ${err.message}`); process.exit(1); });

put accepts either a Buffer or a plain string (it's coerced internally with Buffer.from); get always returns a Buffer or null.

Config

javascript
new VeltrixDBClient({ host: '127.0.0.1', port: 9000, timeout: 10000, // per-operation idle timeout (ms) connectTimeout: 5000, // connection timeout (ms) tls: null, // null = no TLS; object = tls.connect() options })

A single VeltrixDBClient is not safe for concurrent method calls — it processes one operation at a time over one socket. Use VeltrixDBPool when multiple call sites need concurrent access.

API surface

All methods return Promises.

Core key-value

MethodDescription
connect()Open the TCP connection
ping()Check connection health
put(key, value)Write a key (value can be Buffer or string)
get(key)Read a key. Returns Buffer or null
delete(key)Delete a key
info()Get server stats string
auth(user, pass)Authenticate
close()Close the connection

Batch operations

MethodDescription
multiPut(entries)Write multiple keys. Returns array of errors (null = success)
multiGet(keys)Read multiple keys. Returns array of Buffer or null
javascript
const entries = [ { key: 'user:1', value: Buffer.from('{"name":"Alice","age":30}') }, { key: 'user:2', value: Buffer.from('{"name":"Bob","age":25}') }, { key: 'session:abc', value: Buffer.from('token-xyz'), ttl: 60 }, // 60s TTL ]; const putErrors = await c.multiPut(entries); const failures = putErrors.filter(Boolean); const keys = ['user:1', 'user:2', 'user:3', 'user:missing']; const values = await c.multiGet(keys); for (const [key, v] of keys.map((k, i) => [k, values[i]])) { console.log(v !== null ? `${key} = ${v.toString()}` : `${key} → not found`); }

Namespaces

MethodDescription
putNS(ns, key, value, ttl)Write into a namespace
getNS(ns, key)Read from a namespace
deleteNS(ns, key)Delete from a namespace
scanNamespace(ns, prefix, limit)Scan keys in a namespace
listNamespaces()List all namespaces and key counts
dropNamespace(ns)Delete all keys in a namespace

Hash fields (per-field TTL)

MethodDescription
hset(key, field, value, ttl=-1)Set a field with its own TTL
hget(key, field)Get a field value (null if not found/expired)
hdel(key, field)Delete one field
hgetAll(key)Get all live fields as [{field, value}, ...]
hkeys(key)Get all live field names
hlen(key)Count live fields
hexpire(key, field, ttl)Update TTL of an existing field
httl(key, field)Remaining TTL in seconds (-1=forever, -2=not found)

Atomic operations

New in v1.1.0 — typed atomic ops (previously Rust/C++ only). All are Promise-based; each takes an optional trailing ttl in seconds for the stored value (-1 = no expiry):

MethodDescription
cas(key, expected, newValue, ttl=-1)Compare-and-swap. Resolves to 'swapped', 'mismatch', or 'notfound'
incr(key, delta=1, ttl=-1)Atomically add delta; resolves to the new value (Number). Missing keys start from 0
decr(key, delta=1, ttl=-1)Atomically subtract delta; resolves to the new value (Number). Missing keys start from 0
setnx(key, value, ttl=-1)Set only if absent. Resolves to true when created, false when the key already existed
javascript
// Counter — missing key starts from 0 let n = await c.incr('counter', 5); // 5 n = await c.decr('counter', 2); // 3 // Compare-and-swap (expected/new accept Buffer or string) const outcome = await c.cas('hello', 'world', 'earth'); switch (outcome) { case 'swapped': console.log('replaced'); break; case 'mismatch': console.log('value did not match'); break; case 'notfound': console.log('key does not exist'); break; } // Set-if-absent with a 30-second TTL (lock-style) const acquired = await c.setnx('lock', 'owner-A', 30); if (!acquired) console.log('someone else holds the lock');

Connection pool

javascript
const { VeltrixDBPool } = require('veltrixdb-client'); const pool = new VeltrixDBPool({ host: '127.0.0.1', port: 9000, poolSize: 8, // 8 connections acquireTimeout: 5000, // wait up to 5s for a free slot }); await pool.connect(); // 50 concurrent writes — pool distributes across 8 connections await Promise.all( Array.from({ length: 50 }, (_, i) => pool.execute(c => c.put(`concurrent:${i}`, Buffer.from(`value-${i}`))) ) ); // Functional style const user1 = await pool.execute(c => c.get('user:1')); console.log(`Pool available connections: ${pool.available}`); pool.close();

Each pooled connection handles one operation at a time; concurrent execute calls queue internally until a connection frees up, so throughput scales with poolSize up to your concurrency level.

TLS

javascript
const fs = require('fs'); // Server verification const c = new VeltrixDBClient({ host: 'veltrix.example.com', port: 9443, tls: { ca: fs.readFileSync('ca.crt') }, }); // mTLS (client certificate) const c2 = new VeltrixDBClient({ host: 'veltrix.example.com', port: 9443, tls: { ca: fs.readFileSync('ca.crt'), cert: fs.readFileSync('client.crt'), key: fs.readFileSync('client.key'), }, });

Auth

javascript
const c = new VeltrixDBClient({ host: '127.0.0.1', port: 9000 }); await c.connect(); await c.auth('alice', 'secret'); await c.put('key', Buffer.from('value')); // Pool with auto-auth const pool = new VeltrixDBPool({ host: '127.0.0.1', port: 9000, poolSize: 4, username: 'alice', password: 'secret', // all connections auto-auth on connect });

Error handling

javascript
const { VeltrixDBError } = require('veltrixdb-client'); const val = await c.get('missing-key'); if (val === null) { console.log('not found'); } try { await c.put('key', Buffer.from('value')); } catch (err) { if (err instanceof VeltrixDBError) { console.error('server error:', err.message); } else if (err.code === 'ETIMEDOUT') { console.error('timed out'); } else if (err.code === 'ECONNREFUSED') { console.error('server not reachable'); } }

VeltrixDBError wraps server-side STATUS_ERR responses and protocol-level failures (e.g. a batch-level error on multiPut/multiGet). Socket-level failures surface as regular Node.js Error objects with a code such as ETIMEDOUT or ECONNREFUSED.