beava binary
Server configuration
CLI flags, environment variables, and YAML config — the full surface for spinning up a beava instance. CLI flags win over env vars; env vars win over YAML; YAML wins over the built-in defaults.
Overview
The beava binary boots a single-process feature server. With no flags, no env vars, and no config file present, it listens on 127.0.0.1:8080 (HTTP) and 127.0.0.1:8081 (TCP), persists state under ./.beava/, and accepts events. Three layers tune it:
- CLI flags (highest precedence) — every-day knobs for boot scripts and ad-hoc runs.
- Environment variables — production-friendly overrides; great for container deployments.
- YAML config (lowest precedence; opt-in via
--config) — long-form settings you'd rather not encode in a shell command.
There's no implicit ./beava.yaml lookup. If you want to use a YAML config, point at it explicitly with -c / --config.
# 1. Built-in defaults (good for first-touch + tests) beava # 2. CLI flags only (good for one-off runs) beava --http-addr 0.0.0.0:8080 --data-dir /var/lib/beava # 3. YAML + flag override (production) beava --config /etc/beava/beava.yaml --memory-only
CLI flags
All flags are global — they work whether you boot the server (default) or run a subcommand like beava quickstart.
beava [OPTIONS] [COMMAND]
Load settings from a YAML config file. Optional. There's no implicit ./beava.yaml lookup; if you want a config, point at one explicitly. The resolved config (which path was loaded — or whether built-in defaults applied) is logged at startup.
no default — env + built-in defaults apply when omitted
Override the HTTP data-plane listener address. Highest precedence — wins over BEAVA_LISTEN_ADDR and any --config YAML.
default 127.0.0.1:8080
Override the TCP fast-path listener address. Highest precedence — wins over BEAVA_TCP_HOST / BEAVA_TCP_PORT and YAML. The TCP transport carries the same JSON envelope as HTTP but with sub-millisecond P99 latency on long-lived connections.
default 127.0.0.1:8081
Override both WAL and snapshot directories under a single root: WAL lands at <PATH>/wal, snapshots at <PATH>/snapshots. Highest precedence — wins over BEAVA_WAL_DIR / BEAVA_SNAPSHOT_DIR and YAML.
default ./.beava/ (so ./.beava/wal/ + ./.beava/snapshots/)
In-memory only — no WAL writer, no periodic snapshot, no recovery on boot. State is lost on restart. Use for docker run smoke tests, demo boots, ephemeral CI runs, and any "I'm just kicking the tyres" workflow that shouldn't leave bytes on disk.
default false (durable mode)
Enable POST /reset and OP_RESET — the destructive registry-wipe endpoint. Off by default; production deploys leave it off so they can't be wiped by accident. Equivalent to setting BEAVA_TEST_MODE=1; the flag wins if both are set.
default false
Subcommands
When no subcommand is provided, beava boots the server. One subcommand is exposed in v0:
beava quickstart [--no-file]
Run the in-process 4-step first-touch demo. Spawns an in-process server on an ephemeral port, registers a PageView / SiteMetrics pipeline, pushes 5 events, queries the global row, prints a formatted walkthrough, and writes beava_quickstart.py to the current working directory. Zero setup, zero dependencies, completes in under 10 seconds.
Flags
--no-file— don't writebeava_quickstart.py. Useful for CI / docker-exec runs where leaving a file behind is noise.
Example
beava quickstart # → 4-step demo runs, beava_quickstart.py lands in cwd beava quickstart --no-file # → demo runs, no file written
Environment variables
Every BEAVA_* env var is overridable by a CLI flag of the same scope. Env vars are read once at startup; changes take effect on next boot.
Listener
HTTP listener address.
TCP fast-path host. Set together with BEAVA_TCP_PORT.
TCP fast-path port.
Storage
Directory for the write-ahead log. Created if missing. Beava refuses to start on a network filesystem (NFS / CIFS) — point at local block storage.
Directory for periodic state snapshots. Recovery on boot replays from the most recent snapshot + WAL tail.
WAL tuning
Three knobs shape the WAL's latency / durability / throughput tradeoff. Defaults are tuned for typical fraud-shape workloads; tweak only with measurements.
Number of in-flight WAL buffers (active / sealed / flushing rotation). Higher values smooth out fsync tail latency but pin more memory.
Size of each WAL buffer in megabytes. Larger buffers seal less often; smaller buffers fsync more often.
Maximum time the writer waits before flushing a partially-filled buffer. Lower values give tighter ack latency at higher fsync overhead.
Runtime
Set to 1 to enable /reset and OP_RESET. Equivalent to --test-mode; the flag wins if both are set.
Whether the per-entity memory governor is enforced. Default 1 (enforced — over-budget pushes are throttled). Set to 0 to disable enforcement (governor still observes; you'll see WARN logs instead of throttling).
Number of admin-sidecar I/O worker threads. The data-plane runs single-threaded by design (Redis-shaped); this only sizes the admin runtime that serves /health, /ready, /metrics, /registry.
One of trace, debug, info, warn, error. Equivalent to YAML log_level.
Debug-only
Don't set these in production. They exist for incident response, performance profiling, and crash testing.
Set to 1 to emit per-stage timing for every applied event (parse / validate / route / aggregate / WAL). Adds ~5-15% overhead; expect log volume to spike.
Crash-injection hook for recovery testing. Set to a known checkpoint name to abort the process at that point.
YAML config
The YAML config covers the long-form settings you'd rather not encode in a shell command. v0 keeps it small — listener address and log level. Everything else is set via flag or env.
Point at it with --config; there's no implicit lookup.
# Address and port to bind the HTTP data plane to. listen_addr: "127.0.0.1:8080" # trace | debug | info | warn | error log_level: info
An example file lives at beava.example.yaml at the repo root. Copy and edit; nothing in the schema is required.
Precedence
When the same setting is configured at multiple layers, beava resolves in this order — first match wins:
- CLI flag (e.g.
--http-addr 0.0.0.0:8080) - Environment variable (e.g.
BEAVA_LISTEN_ADDR=0.0.0.0:8080) - YAML config (e.g.
listen_addr: "0.0.0.0:8080") — only loaded if--configis set - Built-in default (e.g.
127.0.0.1:8080)
The resolved config is logged at startup. If beava's bound to a port you didn't expect, check the boot log line that names which layer produced the value.
Default ports and paths
With no flags, no env, no YAML:
127.0.0.1:8080
127.0.0.1:8081
127.0.0.1:8090 — separate port for /health, /ready, /metrics, /registry. Kept off the data-plane port so admin scrapes don't share a runtime with hot-path requests.
./.beava/ — WAL at ./.beava/wal/, snapshots at ./.beava/snapshots/. The directory is created on first boot if missing.
Common questions
Why doesn't beava look for ./beava.yaml automatically?
Because curl … | sh && beava is the canonical first-touch path, and an implicit lookup would force every fresh install to pre-create a YAML file (or hit "config file not found"). The locked behavior: no YAML unless you ask for one with -c. Built-in defaults handle every other case.
Can I run beava without writing to disk at all?
Yes — beava --memory-only. Skips WAL, skips snapshots, skips recovery. State lives in process memory only and is lost on restart. Use it for tests, demos, and CI runs that shouldn't leave bytes behind.
How do I bind to all interfaces in a container?
Pass --http-addr 0.0.0.0:8080 (and --tcp-addr 0.0.0.0:8081 if you want the TCP fast-path reachable). The defaults bind to 127.0.0.1 so a fresh native install isn't accidentally exposed to the network.
Why does WAL refuse a network filesystem?
Because the WAL writer relies on O_APPEND + fsync() semantics that NFS / CIFS / FUSE-style mounts don't reliably honor. A successful fsync() on a network filesystem can return before bytes hit the persistence layer, breaking the durability contract. Beava detects the FS type at boot and refuses to start on a remote mount; point --data-dir at local block storage.
Where are the admin endpoints?
On a separate sidecar port (default 127.0.0.1:8090). /health, /ready, /metrics, and /registry are served there — kept off the data-plane port so observability scrapes don't share a runtime with the hot-path event apply loop.
Where to go next
You've got beava running. Two reasonable next stops: