
When you're evaluating a database, one of the first practical questions is how much machine to give it. Four CPUs? Eight? How much memory? And if you double the hardware, should you expect twice the capacity?
We wanted a more useful answer for people trying Arc. So we ran a sizing campaign on three AWS machines, testing ingestion, queries, and both together. We used native Arc OSS, built from main, and measured what happened with the write-ahead log enabled, disabled, and placed on a separate disk.
The biggest surprise: doubling from 8 to 16 vCPUs did not improve MessagePack ingestion when WAL shared the data disk. The larger machine still had CPU available. Storage was getting in the way.
That finding, along with the rest of the results, is now in our hardware sizing guide. Here's what we tested, what we learned, and how to use it for your own evaluation.
The question we wanted to answer
A peak ingestion number tells you something about a database. Choosing hardware takes more information: your ingestion format, recovery requirements, query workload, and how much history you plan to retain.
We started with single-node Arc OSS. Enterprise clusters introduce replication, topology, and separate node roles; those need their own measurements. These results don't describe Enterprise cluster capacity.
Our goal was to give people ballpark starting sizes, with enough context to explain when a bigger machine helps and when it doesn't.
How we tested
The campaign ran on October 13–14, 2026, in AWS us-east-1, using on-demand instances. Each server ran the same native binary built from main commit 116a318f, with the standard DuckDB query engine. These are main-build results, not measurements of the 26.09.3 release.
| Instance | vCPU | RAM |
|---|---|---|
| m7i.xlarge | 4 | 16 GiB |
| m7i.2xlarge | 8 | 32 GiB |
| m7i.4xlarge | 16 | 64 GiB |
AWS vCPUs here are logical CPU threads, with two threads per physical core. Each machine had a 750 GiB gp3 data volume provisioned for 6,000 IOPS and 500 MiB/s. The separate-WAL experiment added a 250 GiB gp3 volume with the same IOPS and throughput settings.
We tested one Arc server at a time, driven by a separate c7i.16xlarge load generator. The ingestion workload used a timestamp, a host tag, and three numeric fields, sent as either uncompressed columnar MessagePack or line protocol. Each request contained 5,000 points, with 32 ingestion workers. A point is one row; points/sec is not HTTP requests/sec.
After rate sweeps and repeated confirmations, selected ingestion rates had to complete a ten-minute run. We checked HTTP errors, acknowledged rows against persisted rows after draining, and WAL and storage failure counters. A run that returned successful writes but dropped WAL entries did not qualify for the WAL-enabled table.
Query tests used 20 million unique historical points across 24 hours, with either 10,000 or 100,000 distinct hosts. We ran an aggregation query mix at several concurrency levels, keeping profiles whose slowest query type stayed within a two-second p95 in every repeat. The benchmark report includes the workload definitions, configuration, and raw evidence.
Ingestion: format and WAL both matter
Here are the measured ten-minute operating points. M means million points/sec; k means thousand.
| Instance | WAL | MessagePack points/sec | Line protocol points/sec |
|---|---|---|---|
| m7i.xlarge | Enabled, shared disk | 4.02M | 561.4k |
| m7i.xlarge | Enabled, separate disk | 4.44M | 561.3k |
| m7i.xlarge | Disabled | 4.92M | 895.7k |
| m7i.2xlarge | Enabled, shared disk | 8.43M | 1.01M |
| m7i.2xlarge | Enabled, separate disk | 8.01M | 1.01M |
| m7i.2xlarge | Disabled | 9.78M | 1.57M |
| m7i.4xlarge | Enabled, shared disk | 8.15M | 1.90M |
| m7i.4xlarge | Enabled, separate disk | 10.06M | 1.90M |
| m7i.4xlarge | Disabled | 18.22M | 3.00M |
MessagePack had a substantial advantage for this batched workload. If you're building a high-volume ingestion pipeline, it's worth evaluating the MessagePack write path. Line protocol remains useful when connecting existing collectors, and its measured rate increased with each CPU size.
With WAL disabled, MessagePack scaled from 4.92M to 9.78M to 18.22M points/sec. With WAL enabled on the shared disk, it went from 4.02M to 8.43M, then stayed around 8.15M on the largest machine.
That plateau deserved a closer look.
More CPU couldn't fix the shared disk
At higher ingestion rates on the 16-vCPU server, the shared volume reached approximately its provisioned 500 MiB/s throughput while the CPU still had spare capacity. WAL writes and Parquet writes were competing for the same volume.
We moved the WAL directory to a second disk and repeated the ingestion tests. The largest machine's qualified MessagePack rate rose from 8.15M to 10.06M points/sec, about 23% higher.
One comparison explains why we call this a qualified rate. At the same offered load of 10.125M points/sec, the shared-disk run acknowledged about 10.07M points/sec and eventually persisted all its acknowledged rows. But it also recorded 208,332 dropped WAL entries. That run failed our WAL-enabled acceptance checks. With a separate WAL disk, Arc achieved about 10.06M points/sec with zero WAL drops and passed those checks.
We're working to eliminate this WAL-drop scenario under storage pressure in the next version of Arc. These results reflect the behavior of the tested build, before that work is complete.
The benefit was being able to handle that load while meeting the WAL checks. Looking only at successful HTTP responses would have hidden the difference.
A second disk was not a universal speedup. The smaller machines' selected rates varied in both directions, and comparisons at the same offered load were nearly identical. Line protocol throughput barely changed with WAL placement. Separate WAL storage helps when that contention is part of your bottleneck; it doesn't automatically double capacity. Both volumes also share the instance's aggregate EBS bandwidth.
Disabling WAL removes work and can increase throughput, but it changes recovery behavior. Use it only when losing buffered writes after an abrupt failure is acceptable. The WAL-enabled configuration here used buffered, periodic synchronization; it was not a per-request durable acknowledgment barrier. These were throughput and accounting tests, not crash-durability tests. The WAL documentation explains the recovery behavior and configuration.
Queries benefited from the larger machines
The query-only results, with WAL enabled, looked different from the shared-disk ingestion plateau:
| Instance | QPS, 10k hosts | QPS, 100k hosts | p95, 10k hosts |
|---|---|---|---|
| m7i.xlarge | 2.90 | 2.32 | 1.28s |
| m7i.2xlarge | 5.49 | 3.89 | 1.52s |
| m7i.4xlarge | 10.94 | 7.79 | 0.71s |
QPS means queries per second. The p95 column reports the slowest query type's latency. These are aggregation queries over the seeded dataset, so the rates describe that workload rather than every SQL query Arc can run.
Going from 8 to 16 vCPUs roughly doubled query throughput. Increasing the number of distinct hosts lowered throughput on every machine. The query profiles used different selected concurrency levels, so latency doesn't have to decrease at each step in the table.
For sizing, this matters: you may need the larger machine for query demand even when your write rate fits comfortably on a smaller one.
Ingesting and querying together changes the answer
An ingestion-only result and a query-only result can't simply be added together. They use the same machine, and the data keeps growing while queries run.
We also tested 100,000 MessagePack points/sec with concurrent aggregation queries. Each ten-minute run grew from 20 million to 81.5 million rows, including warmup. These are tested combinations with WAL enabled, not maximum mixed-workload capacities:
| Instance | Write points/sec | Query QPS | Query p95 |
|---|---|---|---|
| m7i.xlarge | 100.0k | 0.29 | 2.56s |
| m7i.2xlarge | 100.0k | 0.55 | 1.38s |
| m7i.4xlarge | 100.0k | 1.09 | 0.72s |
WAL-disabled runs at this write rate produced similar query results; the sizing guide includes both sets. We tested separate WAL placement for ingestion only.
Higher query demand slowed responses and missed the requested query rate even while ingestion kept up. The four-vCPU combination above also exceeded a two-second query p95. A write target alone would have made that machine look sufficient; the application's latency target might rule it out.
Where to start your evaluation
For WAL-enabled evaluations on comparable storage, our guide reserves approximately 50% headroom below measured rates:
| Instance or equivalent | vCPU | RAM | MessagePack points/sec | Line protocol points/sec | Query-only QPS |
|---|---|---|---|---|---|
| m7i.xlarge | 4 | 16 GiB | 2.00M | 280k | 1.4 |
| m7i.2xlarge | 8 | 32 GiB | 4.20M | 500k | 2.7 |
| m7i.4xlarge | 16 | 64 GiB | 4.00M | 950k | 5.4 |
The write and query columns describe separate workloads. Use the combined results when both run together. The 16-vCPU MessagePack starting target reflects the shared-disk result; a larger CPU allocation doesn't make a fixed storage budget disappear.
These are ballpark targets from short benchmarks. The tested EC2 sizes have different sustained EBS and network baselines, and smaller instances can burst above them. A ten-minute run does not establish continuous capacity above those baselines. Check the sustained limits of both your instance and your volumes, then test your own schema, query mix, and retained history.
Retention can dominate the hardware decision too. Our unique historical dataset used about 28 bytes per point, rounded up for this three-field schema:
| Write rate | Retention | Stored data |
|---|---|---|
| 10,000 points/sec | 30 days | ~676 GiB |
| 100,000 points/sec | 30 days | ~6.6 TiB |
Those figures cover stored data. Add room for WAL, compaction output, temporary spill, and free disk headroom. Measure bytes per point with your own data; a narrow telemetry row and a large log message have very different storage costs.
Try Arc with your workload
The useful outcome of this campaign is a place to start and a clearer way to interpret the results. Watch CPU, memory, storage throughput, flush backlog, and query latency together. If ingestion stops scaling while CPU remains available, inspect the storage path before buying more CPUs.
Download Arc and follow the native installation guide to run it on your infrastructure. Use the hardware sizing guide to choose a starting machine, connect your collector or MessagePack client, and run the queries your application actually needs.
The benchmark report and raw results are public. Run the tests, adapt them, and tell us what you find on Discord or GitHub.
If you're evaluating a clustered production deployment, talk to us about Arc Enterprise. Enterprise sizing is the next part of this work, with replication and node roles measured separately.