Berserk Docs

Hardware Sizing

A guide to sizing hardware for a Berserk cluster.

This page is a guide to sizing the hardware for a Berserk cluster: how many cores, how much memory and disk, and how much object storage to plan for.

What drives the size

In this guide we size a cluster from the following properties of your workload:

  • Ingest per day: how much telemetry you send, measured as uncompressed OTLP data.
  • Retention: how long you keep data. This sets object storage capacity.
  • Query cache retention: how many days you want on local disk for fast searches. This sets the disk on query nodes.

The coefficients below are guiding principles from measured installations and scale linearly. Treat them as a plan, then verify against your own cluster's metrics.

Start with the calculator below; the sections after it explain the numbers behind it and what each service needs.

Calculator

Compute

Ingest1 cores, 2 GB RAM
Query (starting point)4 cores, 8 GB RAM
Total5 cores, 10 GB RAM
PostgreSQL2 cores, 2 GB

Storage and network

Stored per day100 GB
Query cache disk (NVMe)300 GB
Object storage (S3)3 TB
Network in0.093 Gbit/s

Example machines

Single node8 cores (16 vCPU), 16 GB RAM, 400 GB NVMe
Highly available3 nodes of 4 cores (8 vCPU), 8 GB RAM, 200 GB NVMe

The numbers

Compression: 10x, depending on your data. Berserk will compress data before storing it. Ingest is measured as uncompressed OTLP protobuf. Stored segments are about 10x smaller. Repetitive logs compress better, high-cardinality traces worse.

Ingest: 1 TB/day per core. The amount of data one modern physical core can ingest per day through the whole pipeline: receiving, converting to segments, and merging. A core is a physical core; on x86 cloud instances that is two vCPUs, on ARM instances (Graviton, Axion) one vCPU is one core.

Query: start at 4x the ingest cores. Query cost depends entirely on the search load you put on the cluster, so there is no formula. Four times the ingest cores is a starting point for a cluster with normal interactive use; heavy dashboards or many concurrent users need more.

Memory: 2 GB per core. Query tends to use more memory than ingest when doing many parallel queries or queries with large states. So typically query nodes will use more RAM than we do in the ingest pipeline (ingest, nursery and janitor).

Query cache disk: ingest / compression x cache days. Query nodes cache segments from object storage on local SSD or NVMe. Size the cache for the number of days you want available for fast searches. Older data is still searchable, read from object storage.

ResourceRule
Compression10x, data dependent
Ingest CPU1 TB/day per core
Query CPU4x ingest cores, starting point
Memory2 GB per core
Query cache diskingest / compression x cache days, SSD or NVMe
Minimum cluster4 cores, 8 GB RAM

The coefficients are for average ingest. If your peak hour is twice your average, size for the peak.

  • PostgreSQL: a small instance, 2 cores and 2 GB, with a little disk. Do not use a burstable instance type.
  • Object storage: ingest / compression x retention days of capacity. Berserk depends heavily on a well-functioning S3-compatible object store; setting one up is another important discussion.
  • Network: 10 TB/day of ingest is about 1 Gbit/s inbound.

Examples

ExampleCores (ingest + query)RAMCache diskS3Example machines
1 TB/day, 30 days retention, 3 days cache1 + 4 = 510 GB300 GB3 TBSingle node: 8 cores (16 vCPU), 16 GB RAM, 400 GB NVMe
Highly available: 3 nodes of 4 cores (8 vCPU), 8 GB RAM, 200 GB NVMe
10 TB/day, 1 year retention, 7 days cache10 + 40 = 50100 GB7 TB365 TBLarger nodes: 4 nodes of 16 cores (32 vCPU), 64 GB RAM, 2 TB NVMe
Smaller nodes: 7 nodes of 8 cores (16 vCPU), 16 GB RAM, 1.5 TB NVMe
100 TB/day, 90 days retention, 7 days cache100 + 400 = 5001 TB70 TB900 TBLarger nodes: 16 nodes of 32 cores (64 vCPU), 128 GB RAM, 5 TB NVMe
Smaller nodes: 32 nodes of 16 cores (32 vCPU), 64 GB RAM, 2.5 TB NVMe

Machine suggestions assume x86 (vCPU counts are two per core) and one query node per machine; the NVMe per node is its share of the query cache with 10% headroom. Where the whole cluster fits on one machine, the table shows that option first; a single node is not highly available. Three or more nodes tolerate the loss of one; see Deployment for the rest of a highly available setup.

Details per service

The overview treats ingest as one number. It is three kinds of pods, and this is how the ingest cores and memory split between them when you write Helm values. Roughly 60% of the ingest CPU goes to the nursery, 40% to the janitor, and 5% to the collector.

Ingest collector

Receives OTLP, batches it, and uploads raw batches to object storage. About 5% of the ingest cores; scale it for burst, not for average rate. Memory is burst absorption: in-flight data is capped at 60% of the pod's memory limit, so the limit decides how many seconds of incoming data the collector can hold while object storage is slow. Plan for at least 1 GB. No local disk.

Nursery

Converts raw batches into segments and merges them locally. About 60% of the ingest cores, and a few large pods are better than many small ones. Memory is 2 GB per core. It needs 50 GB of local working disk per pod for baby segments; ordinary node storage is fine.

Janitor

Merges segments in object storage into larger ones. About 40% of the ingest cores, but a merge is single-threaded, so run it as replicas of one core each rather than one large pod. Each replica uses whatever memory limit it is given for merge buffers and does more passes with less; plan for 2 to 4 GB per replica. Each replica needs 30 GB of scratch disk at the default settings, and that is a hard cap: a replica that overruns it is evicted mid-merge.

Query

Executes searches and holds the segment cache. Cores and memory are the 4x and 2 GB per core starting points above. Each query pod owns a share of the cache proportional to its CPU limit, so with one query pod per node the cache disk is spread evenly across nodes; provision each node's volume a little larger than its share. Memory beyond what queries use becomes page cache over the segment cache, which is the cheapest read speedup there is. See Storage and Segment Placement.

Meta

The metadata service. It tracks tables, segments and ingest streams in PostgreSQL and answers the lookups every query starts with, so its latency is on the path of every query. It needs a fraction of a core and a few hundred MB of memory at any scale; keep it close to the database.

Control plane

The UI, gateway and permissions service together use a fraction of a core and under 1 GB of memory at any scale.

PostgreSQL

Holds metadata: segments, streams, users and permissions. It is small and grows with the number of segments, but it sits on the path of every query, so a slow or throttled database stalls the whole cluster. 2 cores and 2 GB on a non-burstable instance is enough for the clusters on this page.

Object storage

Capacity is ingest / compression x retention days, plus the raw batches waiting to be converted, which is a day or less of ingest. Every byte is written and read more than once as it moves from raw batch to segment to merged segment, so sustained throughput matters as much as capacity. Choosing and configuring the object store is its own topic and not covered here.

On this page