Skip to main content

Overview

A self-hosted Bud deployment has two resource layers, and sizing each one separately is the key to right-sizing your infrastructure:

Platform services

The control plane — dashboard, APIs, gateway, databases, queue, object storage, and monitoring. Memory is a largely fixed baseline; CPU scales with request throughput and is the binding constraint for high-throughput agent/event traffic — load testing runs out of CPU well before memory.

Inference nodes

Where your models actually run. The dominant cost at scale. Provisioned on dedicated inference nodes whose hardware — GPU, CPU, or HPU — is chosen per model based on the model, use case, and latency/throughput (SLO) targets. The platform recommends the node type and configuration when you deploy each model.
Plan the platform services first (a relatively fixed footprint), then add inference nodes of the appropriate type — CPU, GPU, or HPU — for the models you intend to serve. The two layers scale independently.

Choosing inference hardware

You add inference capacity by attaching nodes with the accelerator that best fits each model and its service-level objectives. The platform’s optimizer analyses the model and target SLO and recommends the node type and count.
HardwareTypical fit
GPU (CUDA)Largest models, lowest latency, highest concurrency
CPUSmaller / quantized models, batch or latency-tolerant workloads, cost-sensitive sites
HPU (Intel Gaudi)High-throughput serving where Gaudi accelerators are available
A single deployment can mix node types — for example, GPU nodes for latency-critical models and CPU nodes for smaller or background workloads.

Choosing a deployment size

The tiers below are sized by concurrent requests (requests in flight at once), not named users. Convert to/from throughput with concurrent ≈ requests/sec × average request latency — e.g. 1,000 req/s of a 10-second agent turn is ~10,000 concurrent. Holding concurrency is cheap on memory (~1–2 MiB per in-flight request on the platform, measured on the event path); CPU is driven by throughput (req/s) and is the resource that runs out first for high-throughput agent/event workloads. Size CPU to your peak req/s, not to a user count.
One machine running the full platform plus one or more models locally. Suitable for evaluations, edge sites, and small teams (up to ~100 concurrent requests).
ResourceMinimumRecommended
CPU16 cores32 cores
Memory96 GiB128 GiB
Storage (NVMe SSD)1 TiB2 TiB
Inference acceleratorCPU-only (smaller / quantized models)1 × 48–80 GB GPU for larger models or low-latency serving
The platform services alone use roughly 50–60 GiB of memory, so 64 GiB is not enough once a model and the operating system are added. Likewise, the fixed storage footprint already exceeds 200 GiB before model files — start at 1 TiB.
Smaller or quantized models can serve on CPU. A single 48–80 GB GPU comfortably serves one model in the ~20–30B-parameter range at low latency. Larger models or higher concurrency call for the clustered tier.

Storage planning

Storage falls into three independent components. They scale on completely different axes, so size each one separately rather than picking a single total:
ComponentScales withBounded?
Platform baselineFixed footprint — databases, queue, object-store metadataYes, roughly fixed
Model storageNumber and size of the models you onboardNo — grows with your catalog
Analytics & observabilityRequest rate × retention windowYes — plateaus at the retention window

Platform baseline

Independent of traffic and of your model catalog, a deployment provisions storage for its databases, message queue, and object-store metadata. Plan for roughly 200–500 GiB for this layer before any model files or request data.

Model storage

The model registry — where downloaded model weights live — is usually the largest and least predictable part of total storage, and it scales with your model catalog, not with the deployment tier. Size it explicitly. Per model, registry size ≈ parameters × bytes-per-parameter × variants kept:
PrecisionBytes/param8B70B405B
bf16 / fp162~16 GB~140 GB~810 GB
fp8 / int81~8 GB~70 GB~405 GB
int4 (quantized)0.5~4 GB~35 GB~200 GB
Bud often keeps more than one variant of a model — for example the original weights plus a quantized copy — so multiply by the number of variants you retain. Example registry sizes. Most catalogs fall into a few tiers. Use these as a starting point, then refine with the formula above for your exact model list:
Registry tierExample catalogApprox. catalog sizeSuggested registry capacity
EvaluationOne 8B chat model (bf16) + a small embedding model~20 GB50 GiB
Small catalogA few 7–32B models, one of them quantized, + embeddings and a reranker~50–100 GB200 GiB
ProductionA 70B model kept as both bf16 and int4, + 8–32B models and embeddings~250–500 GB500 GiB – 1 TiB
Large / multi-tenantA quantized 405B model + several 70B/32B variants + a multimodal model + embeddings~1–3 TB2–5 TiB+
The suggested registry capacity column is what to provision for the registry volume and set as MODEL_REGISTRY_MAX_SIZE; it adds headroom above the raw catalog size for variants you add later and for the local download cache. Model weights occupy storage in up to three places; budget for all of them:
  • Registry (durable copy) — one copy per model variant in the object store (SeaweedFS by default; any S3-compatible store — Ceph / rustfs — works). This is what the registry budget, MODEL_REGISTRY_MAX_SIZE, governs.
  • Local download cache — staging on the model-registry volume while a model is fetched, before it is uploaded to the registry. Provision at least your largest model × the number of concurrent downloads.
  • Inference model volume — when a model is deployed, its weights are placed on a volume the inference pool mounts. Use a shared (ReadWriteMany) storage class — NFS, AWS EFS, Azure Files, or similar — so the pool keeps one copy of each model regardless of node count; size it to the models that pool serves. (A node-local ReadWriteOnce volume works for single-node serving, but then each node needs its own copy.) Note the trade-off: shared network-attached storage (NFS, AWS EFS) saves space but can slow model load times at pod startup/scale-up compared with node-local NVMe — back it with fast storage, or use a node-local cache for latency-sensitive cold starts.
The registry runs a pre-flight capacity check before every download, so an over-full registry fails fast instead of part-way through a multi-gigabyte upload. Set MODEL_REGISTRY_MAX_SIZE to your provisioned registry capacity and grow the backing volume as your catalog grows — see Helm Configuration.

Analytics & observability growth

Usage data grows with traffic but is bounded by retention windows, so it reaches a steady state rather than growing forever. Two kinds of data accrue per request and scale very differently — size them separately:
DataWhat it isScales withDefault retention
Inference analyticsOne metadata row per request (tokens, latency, model, status)requests/sec90 days
Observability tracesRaw spans — ~8 per LLM request, ~15 per agent invocationspans/sec (≈ req/s × spans-per-request)30 days (configurable)
Usage metricsAggregated dashboards and billing rollupsrequests/sec90 days
Traces are normally the dominant driver. A request isn’t one record — it’s a tree of spans (gateway + model + agent orchestration). At a measured ~385 bytes per span, an agent invocation’s ~15 spans is ~5–6 KB of trace data, versus ~0.1–0.2 KB for its metadata row. Size the two terms separately:
fact_bytes/day   ≈ bytes_per_request × requests/sec × 86,400
trace_bytes/day  ≈ spans_per_request × bytes_per_span × requests/sec × 86,400
steady-state     ≈ (fact + trace) bytes/day × retention-days × replication (3) × ~1.3 merge headroom
As a guide, at a sustained 1,000 requests/second (metadata-level — no content capture; provisioned across 3 HA copies):
ComponentSteady-state (3 copies)
Inference analytics — metadata rows (90-day)~5 TB
Observability traces — bare LLM requests, ~8 spans (30-day)~30 TB
Observability traces — agent workloads, ~15 spans (30-day)~55–60 TB
+ full request/response content loggingstacks ~2–3 KB per content-bearing span on top
Traces carry a 30-day window and scale with spans-per-request, so the observability retention window and span volume — not the metadata rows — are your primary storage levers. Scale linearly for other rates (100 req/s ≈ one tenth).
Measured on a 100M-request reference dataset: the per-request metadata fact is ~126 bytes/row (11.8 GiB compressed per replica per 100M requests), while raw trace spans are ~385 bytes each and agent invocations average ~15 spans — so traces are ~90% of per-request storage. The biggest levers are the observability retention window, span sampling, and keeping content capture off unless you need it.
Enabling full request/response content logging substantially increases storage. If you turn it on, set an appropriate retention window first and provision accordingly.

Keeping storage predictable

  • Prune unused models and stale quantized variants from the registry — for most deployments the model catalog, not request volume, is the largest storage driver.
  • Tune the observability retention window to your needs (shorter = less storage).
  • Keep full request/response logging off unless you need it, and bound it with a retention window when you do.
  • Use premium SSD/NVMe for databases and the model registry; standard SSD is fine for general application data.
  • For very large datasets, scale the analytics database horizontally rather than relying on replication alone.

Scaling

Platform services

  • Memory is a largely fixed baseline (databases, queue, monitoring) plus a small per-request working set (~1–2 MiB per concurrent request, measured on the event path) — provision it generously, but it rarely leads.
  • CPU scales with request throughput and is usually the binding constraint for high-throughput agent/event paths — size it to peak req/s with headroom, not as an afterthought. Every service pod also runs a Dapr sidecar, so per-pod CPU (and the total across many replicas) is higher than the app container alone.
  • Stateless services support horizontal autoscaling (enable it per service for high availability and burst handling). The public event edge (budevent) holds one in-flight turn per concurrent request (~1 MiB each) and caps per pod, so roughly ~10,000 concurrent needs ~20 edge replicas — scale the edge out alongside throughput, and keep a warm minReplicas floor so a sudden spike lands on enough pods before autoscaling catches up (~60–90 s).
  • Run three copies of stateful services for high availability in the clustered and large-scale tiers. Note the shared databases (Postgres connection limit; the analytics store) are a stateful ceiling that scaling stateless replicas does not lift — scale the datastore itself for high req/s.

Inference nodes

  • Add inference nodes to increase serving capacity. Choose the accelerator — GPU, CPU, or HPU — based on each model and its SLO; the platform recommends the node type and configuration at deployment time.
  • Scale out by adding model replicas across inference nodes as concurrency grows.
  • Keep inference nodes in a separate node pool from the platform services so the two scale independently, and mix node types to match each model.

Networking

TrafficMinimumRecommended
Between nodes5 Gbps10–40 Gbps (higher for inference pools)
Internet ingress/egress1 Gbps5 Gbps

Next steps

Installation Guide

Deploy the platform on Kubernetes

Helm Configuration

Configure resources, retention, and services

Deployment

Deployment options and workflows