Skip to main content

Two independent axes — pick each separately

A deployment is defined by two orthogonal choices. Conflating them is the most common sizing mistake:

Availability tier (T0 → T4)

The failure domain you survive — node → zone → region. This is what the tiers below set, and it drives your SLA. It changes topology, not capacity.

Concurrency (sizing)

How many users/requests you serve. This sizes CPU, memory, disk, replicas, and shardswithin any tier. The platform and inference layers scale independently (see Hardware Requirements).
The per-tier user counts below are typical pairings, not caps. 10,000 users doesn’t force T4 — you go to T4 to survive a region outage, not to hold more users. Need 10,000 users but single-region resilience is acceptable? Run a T2/T3 topology sized for 10,000. Pick the tier for failure domains; size for concurrency separately.

The tier ladder

Per-tier reference architectures

AI-in-a-Box — dev / PoC only. Every component on one node. No HA and no backup by design — data is disposable (RPO unbounded). Use only where outage and potential data loss are acceptable.T0 Single-Node reference architecture

Sizing the storage — the bare-minimum volume math

The dominant, variable storage driver is observability traces, and it scales with throughput × retention, not the tier. Total storage is the sum of four components — don’t size on traces alone:

From concurrency to terabytes

1

Concurrency → req/s

req/s = concurrency ÷ avg request seconds. An agent request runs ~15 s (multi-step), so 1,000 concurrent users ≈ 67 req/s. Use your own measured request duration if it differs.
2

req/s → TB

TB ≈ (spans/req × 385 B × req/s × 86,400 × retention-days × 3 (replicas) × 1.3 (merge)) ÷ 10¹² (the ÷ 10¹² converts bytes to TB). Agent invocations average ~15 spans/req; traces are ~90% of per-request storage.
Baseline (agent workload, ~15 s/request, 90-day traces, ×3):
Sized for the agent workload (~15 s/request, ~15 spans). The two levers that move these numbers most are the retention window (linear) and spans per request (fewer spans → proportionally less) — see the knobs below. Plug your own measured request duration and span count into the formula for an exact figure.

What the “external object store” actually is

Bud reaches object storage through a plain S3 API (externalServices.s3: endpoint + keys + bucket). By default it’s SeaweedFS, in-cluster — running on the same nodes’ NVMe, so there is no external store until you add one. The “external” store is simply a separate S3-compatible object store you stand up and operate yourself, then point that config at:
  • Self-hosted SeaweedFS (most common on-prem) — a small cluster of cheap-disk nodes (HDD / standard-SSD, erasure-coded ≈ 1.5× raw). The same stack Bud runs in-cluster, stood up separately on cheap-disk nodes.
  • Ceph / RADOS-GW — any S3-compatible store you already operate works too.
  • Cloud bucket (AWS S3 / Azure Blob) — only where the deployment isn’t air-gapped.
It is additional infrastructure to provision and operate — more (cheaper) nodes, not magic and not free. It exists to hold the cold analytics tier and off-site backups on inexpensive media, away from premium NVMe.
Cold-tiering ClickHouse to an external store is operator-configured (a ClickHouse storage_policy plus you provisioning the store) — not a Bud default flag. And the inference model volume is not shared storage: Bud pulls model weights from SeaweedFS to node-local disk (VOLUME_TYPE=local), so no NFS/CephFS is required on the model path.

Scaling up or down — the knobs

Through T3 you stay at the 3-node HA floor — you scale by fitting bigger NVMe into each node’s vg1 pool, not by adding nodes. Only at T4 does trace volume start to drive node count. And even at T4 you can stay all-NVMe (~5–6 big-NVMe nodes) — you tier cold traces to external object storage to save cost, not because it won’t fit.

Next steps

Hardware Requirements

The underlying compute, memory, storage, and inference capacity model

Helm Configuration

Configure resources, retention, replicas, and the S3 endpoint