Skip to main content
The JavaScript SDK (eventdbxjs) is a native Node-API addon (via napi-rs) that speaks directly to the EventDBX control socket over TCP/Cap’n Proto. It targets Node.js services, serverless API routes, and any runtime that exposes standard TCP primitives.

Feature highlights

  • JSON (de)serialisation for aggregate snapshots and event envelopes.
  • RFC 6902 JSON Patch helpers baked into client.patch.
  • Async/await-friendly API surface with Promise-based helpers.
  • Automatic retries with configurable exponential backoff.
  • Per-call overrides for tokens, metadata, patch operations, and archived filters.
  • Cross-platform builds covering macOS, Linux, Windows, and WASI targets.

Install

Requires Node.js 18+ or any runtime that exposes WHATWG fetch, Web Crypto APIs, and raw TCP access to port 6363.

Connect and configure

createClient falls back to environment variables when options are omitted. Set EVENTDBX_HOST, EVENTDBX_PORT, EVENTDBX_TOKEN, and EVENTDBX_TENANT_ID (for multi-tenant deployments) to avoid hardcoding credentials in code. The retry option enables exponential backoff without recreating the client.

Connection lifecycle tips

  • Connect once per process and reuse the underlying TCP socket to avoid repeated TLS/token handshakes.
  • await client.disconnect() during graceful shutdown so the server releases cursors quickly.
  • await client.isConnected() lets you guard re-use when hot reloading in development.

Serverless or Edge entry points

Module-level caches keep the connection alive across invocations in serverless/Edge runtimes that support global scope reuse (Next.js, Remix, Bun’s serverless runtime, or any environment that exposes TCP primitives).

Runtime configuration

VariableDefaultDescription
EVENTDBX_HOST127.0.0.1Hostname or IP address of the control socket.
EVENTDBX_PORT6363TCP port that hosts the control plane.
EVENTDBX_TOKENemptyAuthentication token that the client forwards on connect.
EVENTDBX_TENANT_IDemptyTenant identifier included in the handshake.
Set these variables or pass explicit overrides through createClient. Multi-tenant deployments always require tenantId (or EVENTDBX_TENANT_ID) so the server routes control requests correctly.

Manage authentication and tenancy

Tokens and tenant identifiers can be set globally or per call. Every method that issues a request to the server accepts an optional token, so you can scope permissions to an end-user session without recreating the client.
Use this pattern when a single process talks to multiple tenants or when privileged background jobs share infrastructure with user-triggered API routes.

Retry configuration

Transport-level failures (socket resets, Cap’n Proto decode errors, etc.) can be retried automatically. Retries are disabled by default (attempts = 1), so opt in by setting the retry object:
Backoff doubles per retry until maxDelayMs is hit. Logical server errors (validation failures, authorization errors, etc.) still bubble to your application immediately.

Write aggregates and events

create seeds a snapshot and first event atomically. apply appends new events. patch issues RFC 6902 operations against the requested historical payload, and archive/restore toggle write access while preserving history.

Read aggregates and events

Use get when you need the entire snapshot, select for sparse projections, list to traverse many aggregates, and events for CDC-style replay. All read methods share the same pagination helpers and filter grammar, returning a PageResult whose items contain either aggregates or event envelopes.

Filters, sorting, and pagination

Filters use the same SQL-like shorthand as the EventDBX server (field = value AND other_field > 10), and sort fields accept names such as aggregateType, aggregateId, version, merkleRoot, and archived. Each entry in PageResult.items is the aggregate snapshot or event payload returned by the control socket.
includeArchived, archivedOnly, and request-scoped token overrides are part of the PageOptions passed to list and events. Always feed the returned nextCursor back into the next call when you need to resume pagination after hitting server-side page limits. When you sort aggregates by created_at or updated_at, you can use shorthand timestamp cursors with the same control socket used by eventdbxjs: pass cursor: "ts:<aggregate_type>:<aggregate_id>" alongside the timestamp sort and the server expands it into the full token (ts:<field>:<order>:<scope>:<timestamp_ms>:...) for you.

TypeScript surface area

The SDK exports helper types so you can strongly type payloads, retries, and pagination in your application.
The generated index.d.ts file still types aggregate and event payloads as any, but the runtime values follow the Aggregate and Event shapes above, so you can layer your own domain-specific interfaces on top.