Browse resources

Run your instance / Operate

Usage and costs

What the instance takes in and stores, how big a machine it needs, and where the limits are.

knotel has no per-seat, per-span or per-request pricing. What it costs is what the machine running it costs: the CPU, memory and disk you give the two containers.

What decides the machine size

  • Ingest volume. Spans, log lines and page views per day set the CPU and memory ClickHouse needs to take them in and merge them.
  • Retention. Disk is roughly a day's data on disk times the days each project keeps it. Halving a project's retention halves its share of the disk.
  • Compression. ClickHouse stores each column compressed, and the resource and attribute JSON that repeats on every span compresses to almost nothing. Expect around 10× or better.

As a starting point, a small VM with 2-4 vCPUs and 4-8 GB of memory handles millions of spans a day. Memory matters more than CPU for ClickHouse; the knotel container itself stays small.

Measured: one vCPU, 2 GB, 48 services

Numbers from the instance Filum.ai runs its own platform on, read off it on 28 September 2026, a busy Monday. One shared vCPU, 2 GB of memory, 2 GB of swap and a 47 GB disk - the smallest thing worth calling a server. Nothing is sampled: every span every service emits is stored.

Measured
Machine1 vCPU, 2 GB RAM (+2 GB swap), 47 GB disk
Reporting48 services across 34 projects, 100% of spans kept
Busiest hour4,424,411 spans - 1,229 spans a second, sustained for the hour
Day so far34.6M spans / 5.41M requests in 17¾ hours
knotel container~250 MiB of memory (218-291 across a minute), 4-17% of the one core
ClickHouse container~540-890 MiB, 21-49% of the one core
Free memory1.08 GB of the 1.96 GB still available
On disk195M spans in 7.22 GiB - 40 bytes a span, 14× compression
Whole database8.11 GiB for 234M rows across every table
Image46 MB to pull, 100 MB unpacked

Two things carry that. The span table compresses 14× because the resource and attribute JSON repeats on almost every row, so a span costs about 40 bytes at rest rather than the ~540 it arrives as. And the app process is small because it does little: parse, filter, hand the batch to ClickHouse. The heavy work is ClickHouse's, and ClickHouse is good at it on one core.

This is the floor, not the ceiling
One vCPU is a machine you would not deploy anything else on. The point is not that 1,229 spans a second is a limit - it is that the limit was never reached on hardware this small. Give it two cores and 4 GB and the same shape holds with room to spare.

On 2 GB of memory

The stack starts and serves on a 2 GB VM, but ClickHouse sizes its caches and memory ceiling for a bigger machine and warns that available memory is too low. Add swap, and give ClickHouse a ceiling and smaller caches in one more file under config.d, mounted the way docker-compose.yml mounts docker/clickhouse/config.xml:

docker/clickhouse/low-memory.xml
<clickhouse>
	<max_server_memory_usage>1100000000</max_server_memory_usage>
	<mark_cache_size>268435456</mark_cache_size>
	<uncompressed_cache_size>134217728</uncompressed_cache_size>
	<index_mark_cache_size>67108864</index_mark_cache_size>
	<max_concurrent_queries>50</max_concurrent_queries>
</clickhouse>
Leave background_pool_size alone
Below 10, ClickHouse refuses to start (number_of_free_entries_in_pool_to_execute_mutation must fit in the pool), so its health check never passes and docker compose up gives up on knotel with dependency clickhouse failed to start.

The Usage page

The Usage page shows what the instance takes in and what it holds, for the month:

  • Ingest: requests (ingest and MCP), spans accepted and those rejected, over the batch limit or filtered, data received, log lines and web events, and requests blocked by a key's allowed sources.
  • Spans ingested per day, stacked by project, and a table of the same counters per project.
  • Storage: each ClickHouse table (spans, logs, web events, trace index) with its rows, size on disk and uncompressed size, plus the SQLite file.

Storage is ClickHouse's own measure of its tables, taken now rather than for the month. Deleted and expired rows leave it as background merges run, so it lags a change of retention.

Sizing from your own numbers
Divide the spans table's size on disk by its rows for your bytes per span, multiply by spans per day and by the days you keep. That's the disk you need, from your own data rather than a guess.

Retention is the disk dial

Disk grows with how much history you keep, and per-project retention is how you choose it. A mixed instance is the usual shape: staging, internal tools and noisy side services at 1 day to 7 days, and the production services you investigate at 30 days or more. Shortening a project's retention deletes its older data, so the space comes back rather than only stopping growth.

Filters are the other half: retention shortens what you keep, filters stop spans being stored at all. Sampling in your SDK or Collector cuts volume further.

Scaling limits

  • knotel runs one ClickHouse server. It scales up, with more cores, memory and disk, not out across nodes.
  • The disk is the ceiling on history. Watch the Usage page's storage table and the host's free space; when it runs low, shorten retention on the biggest projects or add disk.
  • An ingest request is at most 5 MB and 5,000 spans (10,000 log records). Senders batch well below that; see Limits.