Guides

HTTP server & other languages

Run ZeeDB locally or on a hosted machine and connect using HTTP from JavaScript, Python, or any language.

Local and remote access

ZeeDB supports an embedded Go API and a standalone HTTP server. The server owns the directory and shares its handle across requests. Applications use the same API locally and remotely; change the URL and token when deploying. Calling HTTP or running a compiled executable requires no Go toolchain. Building from source does.

This experimental single-node server adds no replication, automatic local/cloud synchronization, SQL, tenant isolation, or compare-and-swap. One token grants full database access. It is not a production-certified service.

Start locally

Build once from the repository root, generate a token, and start the binary:

go build -o zeedb.exe ./cmd/zeedb
$env:ZEEDB_TOKEN = [Guid]::NewGuid().ToString('N') + [Guid]::NewGuid().ToString('N')
.\zeedb.exe serve --data ./data --listen 127.0.0.1:8080

Copy the token securely into client environments before starting the server. Keep it stable across restarts; generating another token changes credentials. It must contain at least 32 bytes with no surrounding whitespace. Use a randomly generated secret, kept out of source control. The token is read only from ZEEDB_TOKEN, never a command-line argument. Stop with Ctrl+C (or Unix SIGTERM); the server drains requests and closes the engine.

On Linux/macOS, build with go build -o zeedb ./cmd/zeedb, generate a token with export ZEEDB_TOKEN="$(openssl rand -hex 32)", and run ./zeedb serve --data ./data. The binaries GitHub Actions workflow builds downloadable development artifacts for Windows, Linux, and macOS when manually dispatched or triggered by a version tag. These are not signed or published package releases.

Use HTTP while the server is running; the local CLI cannot open its directory. Separate local and hosted directories are separate databases.

First request

In another PowerShell terminal, set the same token and run:

$headers = @{ Authorization = "Bearer $env:ZEEDB_TOKEN" }
$body = @{
    collection = 'users'
    key = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('1024'))
    value = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('{"name":"Ada"}'))
} | ConvertTo-Json
Invoke-RestMethod http://127.0.0.1:8080/v1/put -Method Post -Headers $headers -ContentType application/json -Body $body
Invoke-RestMethod http://127.0.0.1:8080/v1/get -Method Post -Headers $headers -ContentType application/json -Body $body

API contract

Every route requires Authorization: Bearer YOUR_TOKEN. POST requires Content-Type: application/json, one JSON object, and no unknown fields. Byte fields use standard padded Base64. Collections are JSON strings. Versions and the stats sequence are decimal strings to preserve uint64 precision in JavaScript. Empty values are allowed and returned as "".

MethodPathRequest / response
GET/v1/healthHandle readiness; {"status":"ok"}
GET/v1/statsEngine counters; sequence is a decimal string
POST/v1/put{collection,key,value}; returns {"ok":true}
POST/v1/get{collection,key}; returns {key,value,version}
POST/v1/delete{collection,key}; idempotent; returns {"ok":true}
POST/v1/scan{collection,start?,end?,limit?}; returns {"records":[...]}
POST/v1/batch{"mutations":[{collection,key,value?,delete?},...]}; atomic; returns {"ok":true}
POST/v1/flush{}; synchronous checkpoint; returns {"ok":true}

For example, {"collection":"users","key":"MTAyNA=="} reads key 1024. A response could be {"key":"MTAyNA==","value":"eyJuYW1lIjoiQWRhIn0=","version":"1"}.

Scan start is inclusive, end exclusive. Omit end or send null for unbounded; "end":"" is an explicit empty upper bound. Limit 0/omitted uses the engine maximum of 1000. No collection-listing endpoint, SQL, or opaque pagination token is supplied. See pagination for ordered key boundaries. Each call sees one consistent state; successive calls can observe other writes. Put does not return a version; a separate get could observe another writer.

Bodies are capped at 4 MiB. Default durable engine budgets also apply: 1 MiB encoded batches, 4096 operations, 4 KiB keys, roughly 1 MiB values, 256 MiB live data accounting, and 1000 records / 8 MiB accounting per scan. No custom budget or relaxed-durability server flags are supplied yet.

Errors and retries

API errors have the shape {"error":{"code":"not_found","message":"record not found"}}. Unknown routes and method mismatches use Go’s plain-text HTTP 404/405 responses. Transport failures may have no JSON body; clients must inspect status/content type.

StatusCodeMeaning
400invalid_json, invalid_argumentMalformed body/Base64, unknown fields, invalid arguments
401unauthorizedMissing or wrong token
403origin_not_allowedDirect browser request with Origin
404not_foundRecord absent or deleted
408timeoutContext deadline or cancellation
413body_too_largeBody exceeds 4 MiB
415content_typeMissing or unsupported content type
422resource_limitEngine budget exceeded
503busy, unavailableRequest capacity exhausted or engine failure

At most 64 authenticated requests are admitted concurrently. The operation context lasts 30 seconds; header/read/write timeouts are 5/35/40 seconds. Deadlines cannot interrupt every lock/filesystem call or roll back a WAL commit. A timeout, disconnect, or failure can leave a write outcome unknown. Reconcile through reads before retrying; no idempotency keys or exactly-once delivery are implemented. busy is returned before operation execution.

JavaScript and Python

Set ZEEDB_URL (default http://127.0.0.1:8080) and the same ZEEDB_TOKEN, then:

node examples/http/client.mjs
python examples/http/client.py

These complete, dependency-free examples in the repository write sample records to http-examples, read them, decode Base64, and scan. They are integration examples, not published npm/PyPI SDKs. Other languages call the same HTTP API.

Keep the full-access token in trusted backends, never browser bundles or public mobile apps. Browser code calls your backend, which authorizes users before accessing ZeeDB. Requests carrying Origin are rejected and no CORS is enabled.

Docker and online hosting

The root Dockerfile builds a static executable and runs it as UID/GID 65532, with no Go toolchain in the final image. Set ZEEDB_TOKEN and run from the root:

docker compose up --build -d
docker compose logs zeedb
docker compose down

Compose publishes only 127.0.0.1:8080, with a named volume at /data. down retains data; down -v deletes the volume. Bind-mounted directories must be writable by UID 65532. Stop the server before copying its whole directory for a backup; flush alone does not make a live copy coherent. See offline backups.

Deploy on a VPS or container host with persistent local storage, one replica per directory. Keep the API private behind an HTTPS reverse proxy and firewall, with request/rate limits. Separate proxy/database containers connect over a private container network; localhost is local to each container. Never log tokens. Cloudflare Pages hosts the documentation, not this stateful server. Ephemeral serverless disk and shared/network volumes are unsuitable storage targets.

Alternatively, the binary supports direct TLS:

./zeedb serve --data /srv/zeedb --listen 0.0.0.0:8443 --tls-cert /secrets/fullchain.pem --tls-key /secrets/privkey.pem

Provide both PEM files and arrange certificate renewal/restart externally. Plain public HTTP exposes tokens and data. For hosted clients, set ZEEDB_URL to your HTTPS origin and obtain credentials through the host’s secret manager. Token rotation requires a restart; no overlapping tokens or live rotation exist.

Test storage/deployment limits, backup/restore, and resource headroom for your workload. Authentication/TLS do not establish audited security, production readiness, tenant isolation, replication, or managed backups.

Something to improve?Edit this page on GitHub