Sizing
These are measurements, with the hardware they were taken on. Where something
has not been measured, this page says so rather than estimating it. For the
server’s memory settings and the SONDAR_JAVA_OPTS heap knob, see
What the server needs.
The server
Section titled “The server”| Measured | |
|---|---|
| Memory, default | docker run: 4 GB heap reserved at start, about 4.6 GB resident idle. The Helm chart and Compose files set a 2 GB heap |
Memory, -Xmx1g | about 1.4 GB resident; starts, serves the UI, answers /api/v1/readyz |
| Disk, fresh install | about 200 MB before any data (embedded database and installed apps) |
Disk per GB of logs
Section titled “Disk per GB of logs”On the first five million lines of the public loghub Thunderbird dataset — 868 MB of syslog-style text — the index occupied 238 MB on disk, 0.27 of the raw size, with every setting at its default. The same lines in a default Elasticsearch 8.15 took 623 MB.
On the first twenty million lines (3.25 GB), measured 7 Oct 2026 on the 16 vCPU server described below, the index occupied 1.07 GB, 0.33 of the raw size. A default Elasticsearch took 3.65 GB, or 2.71 GB after a force-merge. So plan on roughly a third of the raw size; the 0.27 above was true of the smaller slice.
Budget on top of that for the recovery log: each shard written to in the last hour keeps up to about 64 MB of recent writes so a replica can catch up quickly, and releases it after an hour.
How well your logs compress depends on how repetitive they are. Measure with your own data before committing to a retention figure.
Ingest
Section titled “Ingest”On a 4 vCPU / 6 GB virtual machine, the server ingested those 868 MB through its HTTP data API in 338 seconds, from a single client sending batches of 5,000 lines — about 2.6 MB/s, a rate of roughly 220 GB per day. That is ingest alone: no searches, dashboards or alert rules were running at the same time, and they share the same CPU and heap.
Plan on about 500 GB/day for a 16 vCPU / 32 GB server with 16 people searching at once. Measured 13 Oct 2026 on two rented Intel Xeon Platinum 8576C virtual machines, the server confined to 16 vCPU and 32 GB: while sixteen searches ran back to back, about 730 GB/day of syslog-style lines (50,000 a second, 168.5 bytes each) and about 800 GB/day of JSON application logs (23,600 a second, 393 bytes each) held steady — half the searches answered within 110-180 ms, 95 % within about 1.2 seconds, and none failed. It held in every run, three to eight runs per condition:
- at the image’s default 4 GB heap as well as at 16 GB;
- with 20 alert rules running every minute alongside;
- with the data replicated on a second server — plan each server of a replicated pair at the same figure; searches got faster, because the replica serves them too.
500 GB/day leaves about a third for peaks. Ingest alone, with nothing searching, reached about 2.6-2.7 TB/day on the same release (below).
One caution at the default heap. Bulk loads of wide JSON lines sent as fast as they will go could stop
a 4 GB server on Java 21 with OutOfMemoryError: one of 33 loads with eight writers and 2 MB batches, and
7 of 20 with 32 writers and 4 MB batches. It was not a real shortage of memory: Java 21’s garbage collector
gives up on an allocation after two retries while native code briefly blocks it (its “GC locker”), with
collectable memory still in the heap. Releases built from 19 Oct 2026 run on Java 25, whose garbage
collector pins the memory native code is using instead of blocking on it (JEP 423), so that failure has no
mechanism there. They set no flag — and do not add GCLockerRetryAllocationCount to a Java 25 release:
Java 25 refuses to start with it. The 20-run load itself has not been repeated on Java 25 yet; on Java 21
a 16 GB heap never failed it (0 of 10). Java 21 releases built from 18 Oct 2026 set
-XX:+UnlockDiagnosticVMOptions -XX:GCLockerRetryAllocationCount=100 in the image’s own jvm.options
(0 of 20 died with it, at no measurable cost to ingest or search); on an earlier Java 21 release, add that
flag to SONDAR_JAVA_OPTS. Since 18 Oct each HTTP Event Collector request also makes two fewer
batch-sized copies of its body (one, made by the HTTP layer, remains). The figures above were measured at
steady rates, where 4 GB never failed.
Sizing by vCPU
Section titled “Sizing by vCPU”Plan on about 70 GB/day per vCPU with 16 people searching at once, about 90-120 GB/day per vCPU with 4, and about 175-195 GB/day per vCPU for ingest alone. The two searching figures held at every size from 4 to 32 vCPU, for syslog lines and JSON application logs alike, on a server that had its machine to itself; ingest alone was measured that way at 4, 8 and 16 vCPU (above about 24, see step 3). Measured 15-16 Oct 2026 on rented Intel Xeon Platinum 8576C virtual machines, the server confined to whole cores, the load sent from another machine:
| Server | 16 searching: syslog / JSON, GB/day | 95 % of searches within | 4 searching: syslog / JSON, GB/day | 95 % within |
|---|---|---|---|---|
| 4 vCPU | 293 / 339 | 4.3 / 4.6 s | 351 or more / 407 or more | 2.0 / 2.3 s |
| 8 vCPU | 571 / 536 | 2.8 / 2.8 s | 702 or more / 807 or more | 1.1 / 1.6 s |
| 12 vCPU | 857 / 1,017 | 1.9 / 2.2 s | 1,051 or more / 1,213 or more | 0.8 / 0.9 s |
| 16 vCPU | 1,160 / 1,096 | 1.4 / 1.2 s | 1,393 or more / 1,890 | 0.7 / 0.8 s |
| 24 vCPU | 1,734 / 1,625 | 0.9 / 0.8 s | 2,097 or more / 2,849 | 0.6 / 0.7 s |
| 32 vCPU | 2,330 or more / 2,683 or more | 0.7 / 0.7 s | 2,331 or more / 2,701 or more | — |
“Or more” means the highest rate tried held, so the limit was not reached. Each figure is the highest ingest rate the server kept (at least 98 % of what was sent) while its searchers ran back to back.
How to use it:
-
Size the vCPU count from GB per day. Searching, not ingest, is what sizes a busy server: with 16 people searching it takes about 2.5 times the vCPU that ingest alone would.
-
Then check search latency. It follows concurrent searchers per vCPU more than the server’s size, and a small server is slower at the same ratio. Measured at the highest ingest each server held; lighter ingest gives faster searches:
Concurrent searchers per vCPU 95 % of searches within 0.17-0.33 (4 searching on 12-24 vCPU) 0.6-0.9 s 0.5 0.7 s on 32 vCPU; 1.1-1.6 s on 8 about 0.7 (16 on 24) 0.8-0.9 s 1 1.2-1.4 s on 16 vCPU; 2.0-2.3 s on 4 about 1.3 (16 on 12) 1.9-2.2 s 2 (16 on 8) 2.8 s 4 (16 on 4) 4.3-4.6 s -
Above about 24 vCPU, raise the repo’s Write concurrency (the number of shards it writes to, 1 by default). One shard caps ingest there: ingest alone at 32 vCPU reached 141 GB/day per vCPU at 83 % CPU with one shard, and 160 at 93 % with four (24 vCPU: 162 with one, 174 with four).
Under what conditions. Thunderbird syslog lines from loghub led by an ISO-8601 time (168.5 bytes each) and JSON application logs (393 bytes), sent to the HTTP Event Collector; one write shard; a 4 GB heap at 4-8 vCPU, 8 GB at 12-16 and 16 GB at 24-32; 20 million lines already stored before searching began. Each searcher ran four searches back to back over all of it — a count of every event, one rare term, events per hour, and one common word’s matches per hour — and every answer was checked before timing. One run per point; repeats at 8 and 16 vCPU agreed within about 5 % (one JSON run was 14-18 % high). Ingest alone used 128-byte syslog lines.
What these figures do not include yet. They were measured on the 13 Oct 2026 release, before two changes. A faster per-minute time chart (16 Oct) served 33-61 % more searches at the same ingest on 16 vCPU, so the 16-searcher figures are likely conservative. Durable writes by default (17 Oct) cost some of the ingest-alone limit — 6 % with 5,000-line requests, 7-15 % with 100-line ones — and nothing measurable below the limit. Neither has been re-measured across the table.
A server that shares its machine with a busy log shipper or generator measured 44-58 GB/day per vCPU with 16 searching; the 500 GB/day figure above was measured that way. Plan from that floor when the server does not have its machine to itself.
Agents
Section titled “Agents”Measured 29 Sep 2026: one server and N agents as containers on a 4 vCPU / 12 GB virtual
machine (Apple silicon, arm64). Each agent was installed with the product’s own install command
and tailed a log file receiving 50 lines per second, so every step is agents shipping, not
idling. Figures are medians of docker stats over two minutes after a three-minute settle. CPU is
a percentage of one vCPU.
| Agents, 50 lines/s each | Server CPU | Server memory | CPU per agent | Memory per agent |
|---|---|---|---|---|
| 0 | 1-3% | about 4.7 GB | — | — |
| 1 | 6-8% | about 4.8 GB | about 1.8% | 110-160 MB |
| 5 | 3-9% | about 4.8 GB | about 1.9% | 115-205 MB |
| 10 | 7-8% | about 4.9 GB | about 1.6% | 95-105 MB |
| 20 | 11-13% | about 4.9 GB | about 1.1% | 105-130 MB |
Server figures and memory are ranges across three complete runs. Per-agent CPU is from the third
run only: the first two ran their log generator inside each agent’s container with a process
started per line, and docker stats counted that (about 4% of a CPU, measured on its own) as the
agent’s. The generator was rewritten and measured at about 0.5% before the third run.
What that means for planning:
- An agent costs 1-2% of one vCPU and roughly 100-200 MB of memory while shipping 50 lines a second.
- Twenty agents shipping 1,000 lines a second between them add about 0.1 of a vCPU to the server, and its memory barely moves: the server’s footprint is its reserved heap, not its agent count.
- Nothing was lost. The third run stopped every generator, counted 568,850 lines written, and found all 568,850 searchable, from all 20 hosts, 16 seconds later.
At twenty times that rate, nothing fell behind either. Five agents each shipping 4,000 lines a second — 20,000 in total — kept the server at about one of the machine’s four vCPUs (95% of one) and 5.0 GB of memory, and all 4,940,226 lines written were searchable 17 seconds after the generators stopped. Each agent at 4,000 lines a second used about 8% of one vCPU.
At twice that again, still nothing lost. Five agents offering 42,340 lines a second between them (the generators’ achieved rate) kept the server at about 2.6 of the machine’s four vCPUs and 4.9 GB, and all 11,140,000 lines were searchable 36 seconds after the generators stopped. That is the highest rate tried; the server is approaching the machine’s limit there, but the point where it falls behind was not reached.
What was not clean about this measurement. Another tool on the same machine ran throwaway
servers of its own throughout, and every step records which: docker stats counts each container
separately, so their work is not in these numbers, but they competed for the same four CPUs. That
is why the server figures are ranges.
Where a small server falls behind
Section titled “Where a small server falls behind”Measured 29 Sep 2026 on a 2 vCPU / 7.4 GB x86 cloud virtual machine (Intel Xeon Platinum
8255C), with nothing else running on it. The server ran with a 2 GB heap
(SONDAR_JAVA_OPTS="-Xms2g -Xmx2g": the default 4 GB heap plus agents does not fit 8 GB), and the
agents and their log writers ran on the same two vCPUs. Each row is one two-minute window: lines
the writers produced, and lines the server indexed, over the same two minutes.
| Agents | Offered, lines/s | Indexed, lines/s | Server CPU (of 200%) | Server memory |
|---|---|---|---|---|
| 1 | 4,447 | 4,717 | 35% | 2.9 GB |
| 2 | 8,726 | 8,764 | 60% | 2.8 GB |
| 4 | 15,995 | 15,398 | 113% | 2.6 GB |
| 6 | 21,680 | 15,934 | 102% | 2.6 GB |
- This box indexes about 15,500-16,000 lines a second, about 1.2 MB/s of these 76-byte lines, or roughly 100 GB a day. Above that, it falls behind: at 21,680 offered it indexed 15,934.
- Falling behind is a queue, not a loss. When the writers stopped, all 16,695,158 lines were searchable 123 seconds later.
- About 16,000 lines a second per vCPU the server gets, on lines this short. Here the agents and writers took roughly one of the two vCPUs; on the 4 vCPU machine above, 42,340 lines a second used about 2.6. On 16 vCPU and longer lines the rate per vCPU in lines halved, while the rate in bytes held at about 1 MB/s per vCPU (below) — plan from bytes.
A 16 vCPU server
Section titled “A 16 vCPU server”Re-measured 13 Oct 2026 on the current release (same CPU, same confinement, the same 128-byte lines): at the default settings — one write shard — the server kept up to 200,000 lines a second and topped out at 238,000-244,000, about 2.6-2.7 TB a day of ingest alone, at the 4 GB default heap and at 16 GB alike. That is 60-95 % above the 7 Oct release below, largely from buffering the recovery log (+52 % at one write shard, measured 9 Oct). More write shards no longer buy ingest, so raise Write concurrency to 4 for faster scanning searches, not for ingest (on this release it cost about 6 % more disk). The 7 Oct measurements on the earlier release:
Measured 7 Oct 2026 on a rented 32 vCPU / 64 GB x86 cloud virtual machine (Intel Xeon Platinum 8576C). The server ran in a container limited to 16 vCPU — eight whole cores with both of their hardware threads — and 32 GB, with a 16 GB heap; the load generators ran on the other 16 vCPU, so they never competed with it. Data: loghub Thunderbird lines averaging 128 bytes, sent to the HTTP Event Collector in batches. Each row is a two-minute window after a one-minute settle.
| Offered, lines/s | Indexed, lines/s | Server CPU (of 1,600%) | Server memory |
|---|---|---|---|
| 19,996 | 20,462 | 246% | 17.6 GB |
| 49,987 | 53,128 | 1,186% | 17.7 GB |
| 99,957 | 95,124 | 1,212% | 17.8 GB |
| 142,988 | 148,403 | 1,316% | 17.9 GB |
| 147,017 (200,000 asked) | 140,385 | 1,279% | 17.9 GB |
| 146,885 (300,000 asked) | 138,367 | 1,280% | 18.0 GB |
- At the default settings, this server indexes about 125,000-150,000 lines a second — 16-19 MB/s, or 1.4-1.6 TB a day of ingest alone. Asked for more, the offered rate stopped rising: across four runs it levelled off between 125,000 and 147,000, while the generators’ own CPUs sat almost idle, so the limit is the server’s.
- It levels off before its CPUs are full, at about 13 of 16 vCPU, because each repo writes to one shard by default. A shard is written in order, so one shard keeps only part of a big server busy: with 12 senders each batch was indexed by a single thread, and with 24 or 48 senders the indexing threads queued behind the shard’s one recovery log.
- On that release, raising the repo’s Write concurrency raised ingest. It is the number of shards the repo writes to (1 by default), in the repo’s settings. At 4, the same server and load took 182,000-184,000 lines a second at 15 of its 16 vCPU, about 2 TB a day of ingest, and every accepted line was searchable 5 seconds after the load stopped. Measured on a new repo set to 4. Other values, and what more shards cost searches and disk, were not measured.
- Nothing was lost. At every load, every line accepted (109,306,421 in the longest run) was searchable 10 seconds after the generators stopped.
- The default 4 GB heap does as well. The two top rates again with the image’s default heap: 143,556 and 145,789 offered, all indexed, at 5.3-5.4 GB of memory instead of 18 GB. A bigger heap does not raise the ingest ceiling — and it did not speed up searches either: the eight searches below ran in the same time on 4 GB, within a millisecond or a few percent. What a big heap buys with many searches at once was not measured.
- Network buffers stayed small: Netty’s direct memory peaked at 128 MB. Do not cap it tightly: under a 512 MB cap the same load ran about 20% slower, which fits how Netty divides memory between threads (it then makes fewer pools), though that cause was not proved. Under a 3 GB cap it was as fast as with none. The server sets no cap; leave it that way.
Agents on the same server. One to a hundred agents, each installed with the product’s install command and shipping a file that grows by 50 lines a second, ran in containers on the other 16 vCPU:
| Agents, 50 lines/s each | Server CPU (of one vCPU) | Lines that arrived |
|---|---|---|
| 0 | 0.3% | — |
| 10 | 5% | all |
| 25 | 8% | all |
| 50 | 5-11% (two runs) | all |
| 100 | 16% | all 2,939,224, from 100 hosts, 15 seconds after the writers stopped |
A hundred agents shipping 5,000 lines a second between them cost this server about a sixth of one vCPU — about 1% of it — and its memory did not move from its reserved heap. Each agent used about 0.5% of a vCPU and 90-130 MB of its own host. The number of agents a server carries was not reached.
One thing to check on hosts that run many agents or containers: the Linux per-user limit on
inotify instances (fs.inotify.max_user_instances, 128 on Ubuntu). Past it, an agent’s collector
cannot start and ships nothing. The agent list shows that agent as Exception within about half a
minute, and the info icon beside the state gives the reason, which names the setting: too many open files: inotify instance limit reached; raise fs.inotify.max_user_instances. To alert on it,
filter the list by state, or poll GET /api/v1/dc/agent/list?state=exception.
sudo sysctl -w fs.inotify.max_user_instances=1024 (and the same line in /etc/sysctl.d/) clears
it; the collector restarts on its own, and the agent returns to Online once it has run for a minute.
Agents installed before this check was added keep showing such an agent as online — upgrade them.
Searching it
Section titled “Searching it”On the same server, the first 20 million Thunderbird lines (each led by its own time in ISO-8601, as most logs are) sent over the HTTP Event Collector, then eight searches an on-call engineer runs, each timed five times after one warm-up. Every answer was checked against a count made independently from the same lines, and every answer was right. Times are the server’s own, median of five:
| Search | Sondar | Elasticsearch 8.15 |
|---|---|---|
| events in one hour | 6 ms | 1 ms |
| one common word, all time (2.1 M hits) | 13 ms | 1 ms |
| one rare host, all time | 5 ms | 1 ms |
| an exact phrase (880,000 hits) | 118 ms | 143 ms |
| the newest 100 lines from one host | 76 ms | 8 ms |
| events per hour, all time (1,042 hours) | 454 ms | 576 ms |
| a word’s matches per hour | 72 ms | 72 ms |
top 10 hosts, extracted at search time (rex; a runtime field in Elasticsearch) | 25.3 s | 21.2 s |
- Lookups an index answers directly are faster in Elasticsearch, single-digit milliseconds against Sondar’s 5-76. Scanning work — phrases, charts over time — is close, or faster in Sondar.
- Fields you only extract at search time cost a scan of every line on both: about 21-25 seconds over 20 million lines here. Extract the fields you group by often when you index them.
- Over the API, each Sondar search took about 40-50 ms longer than its server time (a 5 ms count came back in 55 ms); Elasticsearch added 1-3 ms. The cause was not found.
- The 4 GB default heap gave the same times: within a millisecond on the fast searches, within 6% on the others, and the top-10 extraction was 8% faster.
- Write concurrency 4 makes the scanning searches 2-4.5 times faster. The same lines into a repo set to 4: phrase 56 ms, hourly chart 126 ms, word per hour 35 ms, and the top-10 extraction 5.7 seconds instead of 25 — all faster than Elasticsearch at its default of one shard — while the direct lookups stayed where they were. It cost 31% more disk (1.64 GB) and ingested 8% faster. Elasticsearch was not re-run with more shards.
Getting the lines in, same box, same 16 vCPU, 32 GB and 16 GB heap, eight loaders: Elasticsearch made all 20 million searchable at 146,426 lines a second, Sondar at 97,962 over the Event Collector (109,727 over its JSON data API in an earlier run). Sondar ingests slower and stores smaller: 1.25 GB on disk against Elasticsearch’s 4.40 GB, or 2.87 GB after forcing Elasticsearch to merge its files.
Searching while ingesting
Section titled “Searching while ingesting”The same 20 million lines loaded, then searches from 1, 4 or 16 clients at once, each running the hour count, the rare-host search, the hourly chart and the word-per-hour chart back to back for two minutes — with no ingest, and with more lines arriving at 50,000 and 100,000 a second:
| Ingest asked | Ingest achieved | Searches at once | Searches/s | Median | 95th percentile |
|---|---|---|---|---|---|
| none | — | 1 | 5.4 | 65 ms | 513 ms |
| none | — | 4 | 21.8 | 66 ms | 511 ms |
| none | — | 16 | 68.7 | 77 ms | 719 ms |
| 50,000/s | 50,193 | 1 | 5.2 | 62 ms | 569 ms |
| 50,000/s | 50,157 | 4 | 19.7 | 106 ms | 625 ms |
| 50,000/s | 48,751 | 16 | 50.0 | 95 ms | 1,064 ms |
| 100,000/s | 99,938 | 1 | 4.8 | 64 ms | 664 ms |
| 100,000/s | 98,411 | 4 | 16.9 | 107 ms | 724 ms |
| 100,000/s | 55,498 | 16 | 48.1 | 110 ms | 1,118 ms |
- Up to four searches at a time, ingest kept its rate and searches stayed fast.
- Sixteen searches at once with 100,000 lines a second arriving is past this server’s limit, and it gives way on ingest: it accepted 55,498 lines a second of the 100,000 offered, while searches kept answering, every one of them, in a median 110 ms. Whether the senders were only slowed or some batches were refused was not recorded.
- The slow end of each row (the 95th percentile) is the hourly chart over all 20 million lines.
Metrics against Prometheus
Section titled “Metrics against Prometheus”The standard “devops” shape from the Time Series Benchmark Suite: 1,000 hosts, ten CPU metrics each, a sample every 10 seconds for 12 hours — 10,000 series and 43.2 million samples — sent to Sondar and to Prometheus 3.15 as the same remote-write requests, one engine at a time on the same 16 vCPU and 32 GB. Every answer was checked against values computed from the data itself.
- Storage: Sondar 133 MB, Prometheus 312 MB — about 3.1 bytes a sample against 7.2, 2.3 times smaller. (Prometheus’s whole data directory, its write-ahead log included, was 487 MB.)
- Ingest: Prometheus is about ten times faster: 3.45 million samples a second to queryable, against Sondar’s 361,000.
| Query | Sondar | Prometheus |
|---|---|---|
| one host, one metric, per minute for an hour | 10 ms | 0.1 ms |
| eight hosts, per minute for an hour | 11 ms | 0.3 ms |
| one host, five metrics, per hour for 12 hours | 17 ms | 1.8 ms (5 queries) |
| eight hosts, all ten metrics, per hour for 8 hours | 28 ms | 16 ms (10 queries) |
| every host’s hourly average, 12 hours | 325 ms | 286 ms |
| every host’s hourly average of all ten metrics | 841 ms | 2,868 ms (10 queries) |
| hosts that went over 90% in 12 hours | 110 ms | 273 ms |
| every host’s latest value | 7 ms | 4.6 ms |
Prometheus answers a query about a few series almost instantly; across every host Sondar is close, and faster when one query covers many metrics, which PromQL splits into one query per metric.
A result is cut at a row limit, and now says so. The two “every host” queries return 12,000
and 120,000 rows. At the default settings Sondar returned 10,000 of them; the times above are from a
server started with -e sondar.max.events=200000, where both answers were complete. When this was
measured the cut result carried no error and no warning. It does now: a result cut at its limit
returns "truncated": true in the job’s status and a warning in the same field as a search’s other
warnings. The limit is 10,000 rows by default (sondar.max.events), on the Search page, on
dashboards and through the API; the Search page’s row-limit selector can ask for fewer, and an API
caller can ask for up to sondar.max.events with collectSize.
Not measured yet
Section titled “Not measured yet”- More than 16 searches at once, and searches together with alert rules and dashboards.
- Several server nodes together.
- Hardware other than the machines named above.
When these are measured they will be added here with the hardware and the method.