Skip to main content
Every SDK speaks the same control-socket protocol (Noise + Cap’n Proto via control.capnp) over the control port (typically TCP 6363) and reuses one TCP connection per process. Install the package for your stack, connect once, and reuse the client. Deep dives link to the full language guides.
Prefer SDKs over raw sockets—the clients ship retries, pagination helpers, and typed payload handling so product teams can focus on domain logic.
All clients can route writes to specific plugins with publish targets (plugin[:mode[:priority]]), and accept per-call overrides so you can fan out to analytics, webhooks, or custom workers without rebuilding the client.

See it, shape it

“See It (L-G-S), Shape It (C-A-P-A-R)” is the EventDBX shorthand for the operational verbs—short, visual, sticky, and a clear split between reads and writes. See It — read actions
  • list – paginate across aggregates (or staged aggregates) with consistent filters and limits.
  • get – fetch the latest aggregate state, metadata, and Merkle information in one call.
  • select – return a filtered subset of fields or dot-paths from aggregate state without transferring the full payload.
Shape It — event-writing actions
  • create – register a brand-new aggregate and seed the first event via the control plane.
  • apply – append a new event to an existing aggregate after running schema validation.
  • patch – submit JSON Patch documents that adjust historical payloads.
  • archive – mark aggregates read-only so they remain queryable but reject new events.
  • restore – flip archived aggregates back to active, allowing writes again.

JavaScript

npm install eventdbxjs
import { createClient } from "eventdbxjs";

const client = createClient({
  ip: process.env.EVENTDBX_HOST ?? "127.0.0.1",
  port: Number(process.env.EVENTDBX_PORT) || 6363,
  token: process.env.EVENTDBX_TOKEN,
  tenantId: process.env.EVENTDBX_TENANT_ID ?? "default",
});

await client.connect(); // returns a reusable TCP socket; call disconnect on shutdown
  • Native Node-API addon that speaks Cap’n Proto over TCP with Noise by default.
  • Promise-first API with async iterables for streaming reads; optional per-call token/publish targets.
  • Retries/backoff and verbose/non-verbose mutation responses.
  • Deep dive to JavaScript SDK

Python

python -m pip install eventdbx
from eventdbx import EventDBXClient

with EventDBXClient(
    token="control_token",
    tenant_id="tenant-123",
    host="127.0.0.1",
    port=6363,
) as client:
    latest = client.get(aggregate_type="person", aggregate_id="p-110")
  • Synchronous TCP client; handshake happens on construction and reuses one socket.
  • Noise XX on by default; toggle with no_noise / EVENTDBX_NO_NOISE for lab setups.
  • Optional retries and verbose/non-verbose mutation responses; includes admin helpers for schemas/tenants.
  • Deep dive to Python SDK

Java

<dependency>
  <groupId>com.eventdbx</groupId>
  <artifactId>eventdbx-java</artifactId>
  <version>0.1.8</version>
</dependency>
import com.eventdbx.client.*;

EventDbxConfig config = EventDbxConfig.builder()
    .token(System.getenv("EVENTDBX_TOKEN"))
    .tenant("default")
    .build();

try (EventDbxClient client = new EventDbxClient(config)) {
    client.connect();
    var snapshot = client.get("person", "p-110");
}
  • Blocking control client mirroring Node parity (create, apply, patch, reads).
  • Noise transport via the bundled snownoise native library; retries/backoff configurable.
  • Publish targets, per-call token overrides, and Jackson-based JSON handling.
  • Deep dive to Java SDK

PHP

composer require eventdbx/eventdbx-php
use EventDbx\Client;

$client = new Client([
    'host' => getenv('EVENTDBX_HOST') ?: '127.0.0.1',
    'port' => (int) (getenv('EVENTDBX_PORT') ?: 6363),
    'token' => getenv('EVENTDBX_TOKEN'),
    'tenantId' => getenv('EVENTDBX_TENANT_ID') ?: 'default',
]);

$state = $client->get('person', 'p-110');
  • Native FFI wrapper over the Rust control client; Noise on by default, configurable per client.
  • Per-call publish targets and token overrides; methods return JSON payloads/envelopes.
  • Requires building the bundled native library before first use.
  • Deep dive to PHP SDK

.NET

dotnet add package EventDbx.Client
using EventDbx;

var options = new EventDbxClientOptions
{
    Host = Environment.GetEnvironmentVariable("EVENTDBX_HOST") ?? "127.0.0.1",
    Port = int.TryParse(Environment.GetEnvironmentVariable("EVENTDBX_PORT"), out var port) ? port : 6363,
    Token = Environment.GetEnvironmentVariable("EVENTDBX_TOKEN") ?? throw new InvalidOperationException("EVENTDBX_TOKEN is required"),
    TenantId = Environment.GetEnvironmentVariable("EVENTDBX_TENANT_ID") ?? "default",
};

await using var client = await EventDbxClient.ConnectAsync(options);
  • Async-first TCP client with Noise enabled by default; dispose with IAsyncDisposable.
  • Methods return JSON strings plus cursor metadata; per-call token overrides supported.
  • Snapshot and schema/tenant admin helpers mirror the control plane.
  • Deep dive to .NET SDK

Go

go get github.com/eventdbx/eventdbx-go
package main

import (
    "log"
    "os"

    eventdbx "github.com/eventdbx/eventdbx-go"
)

func main() {
    cli, err := eventdbx.NewClient(eventdbx.Config{
        Host:     os.Getenv("EVENTDBX_HOST"),
        Port:     eventdbx.DefaultPort,
        Token:    os.Getenv("EVENTDBX_TOKEN"),
        TenantID: "default",
        UseNoise: eventdbx.Bool(true),
    })
    if err != nil {
        log.Fatal(err)
    }
    defer cli.Close()
}
  • Synchronous client returning JSON strings; configure connect/read timeouts in Config.
  • Noise NNpsk0 enabled by default; set EVENTDBX_NO_NOISE or UseNoise to disable in labs.
  • Pagination with cursors for aggregates/events plus snapshots and schema/tenant admin helpers.
  • Deep dive to Go SDK

Rust

cargo add eventdbx-client
use eventdbx_client::{ClientConfig, EventDbxClient};

#[tokio::main]
async fn main() -> eventdbx_client::Result<()> {
    let config = ClientConfig::new("127.0.0.1", std::env::var("EVENTDBX_TOKEN")?)
        .with_tenant("default")
        .with_port(6363);

    let client = EventDbxClient::connect(config).await?;
    let _state = client.get_aggregate("person", "p-110").await?;
    Ok(())
}
  • Tokio-native async client with Noise XX enabled by default and configurable timeouts.
  • Request/response builders keep payloads/metadata strongly typed via serde_json.
  • Per-call publish targets, notes, and token overrides for scoped mutations.
  • Deep dive to Rust SDK

Common patterns

  • Config from env: Provide host/port/token/tenant via environment variables so deployments stay portable; most clients also expose explicit option fields.
  • Connect once: Create one client per process/tenant, reuse the TCP socket, and close/dispose on shutdown to release cursors cleanly.
  • Publish targets: Route writes to specific plugins with plugin[:mode[:priority]]; omit targets to fan out to all enabled plugins.
  • Retries/timeouts: Opt into retries/backoff for transport errors and tune connect/request timeouts for your SLOs.
  • Per-call scope: Override tokens per request when scoping permissions to a user session without rebuilding the client.
If your language is missing, open an issue or follow the control protocol in control.capnp to build your own.