Security Data Works

Architecture

Isolation-first security data platforms.

The query that ruins an analyst's afternoon is almost never the one they typed. It is the scheduled detection job that fired on its period somewhere else on the same cluster, backed up behind a dozen of its siblings, and quietly turned a sub-second hunt into a thirty-second wait, so the thing you actually have to design against is co-tenant load rather than raw data volume, and the question that decides the topology is whether your interactive and scheduled work share a host at all.

Reading time: 9 minutes. The load numbers below come from a first-party single-host bench I ran in the lab this spring, and I want to be careful about what they prove, because the failure shape travels and the absolute coordinates do not.

A two-axis quadrant diagram titled A Defensible Move Clears Both Bars, plotting technical win (benchmark, capability, cost model) on the horizontal axis against operational win (a team you can staff runs it day to day) on the vertical axis. Only the top-right quadrant, where both axes are high, is shaded and checked as Defensible Move; the other three quadrants are hatched and labeled Staffable but weak, Fast but unstaffable, and Neither, with a note at bottom left reading Framing diagram, no measured data points.
A defensible move clears both bars: a technical win on the benchmark and an operational win the team can actually staff day to day. Framing diagram, no measured data points.

The wrong axis

Volume is the axis everyone benchmarks, and it is rarely the one that hurts.

Most security-data benchmarks I read measure one thing at a time. They take a single query, run it against a bigger and bigger corpus, and report how the latency grows, which is a useful number for sizing storage and picking a codec but tells you almost nothing about what an analyst experiences at two in the afternoon when the scheduled detection suite is also running. The interactive experience lives on a different axis, because the wait an analyst feels is set by who else is on the host and what they are doing, and that contention shows up long before the corpus gets large enough to matter on its own.

So I wanted to invert the usual test. Instead of asking how fast one query runs, I wanted to find the point where a steady background of scheduled detection jobs starts to ruin the foreground hunt, because that breaking point is the operational fact a SOC actually plans around, and it is the thing a winner- take-all latency chart hides completely. The interesting result is not which engine is fastest in a quiet room. It is how much company a fast engine tolerates before the interactive p95 falls off, and what the fall looks like when it comes.

The setup

One host, an interactive probe, and a scheduled load you turn up.

The bench runs on a single host, a Beelink with a Ryzen 5800H, under WSL2 with 48 GB and 14 threads, and I split the cores deliberately with a cpuset that gives the engine twelve and the client two so the client's own work does not masquerade as engine contention. One engine runs at a time against a 10- million-row connection-log corpus, and the foreground is a small interactive probe whose latency I record against its intended send time rather than its start time, which keeps the slow tail honest under coordinated omission. The background is six pre-registered scheduled shapes on a 60-second cycle, and the whole thing is open-loop, so when a scheduled response is slow the next one still fires on its period and the backlog grows, the way a real scheduler behaves rather than a closed-loop one that politely waits its turn.

The dial is demand, a multiple of the base scheduled rate that I turn up step by step, and the question at each step is simple: has the interactive probe's p95 latency inflected yet. The baseline probe is noisy on its own, with a coefficient of variation in the 43.9 to 47.9 percent range, which is worth stating up front because it sets how sharp an inflection has to be before I will call it a knee rather than noise. The pre-registration is strict about that: a knee counts only if it reproduces three times at the same step.

The finding

Flat through 32x, and then a knee at 64x.

Three engines held the line in a way I did not expect to be this clean. ClickHouse reading its native tables, ClickHouse reading the same data over Iceberg, and StarRocks all kept the interactive p95 flat across the whole ladder up to 32x co-tenant scheduled load, and "flat" here is not a figure of speech, because just before the knee the p95 sat at roughly 0.099 seconds for ClickHouse native, 0.193 seconds for ClickHouse over Iceberg, and 0.112 seconds for StarRocks. A hundred-odd milliseconds at the ninety-fifth percentile, while a scheduled detection load thirty-two times the base rate runs in the background, is a quiet host.

Then at 64x the curve inflects sharply for all three, and the p95 jumps to about 3.21 seconds for ClickHouse native, 2.70 seconds for ClickHouse over Iceberg, and 3.77 seconds for StarRocks. That is a real knee, a sudden order-of-magnitude move that the prior steps gave no hint of, and I reproduced it three times at the same step, so it clears the pre-registration bar rather than being a single noisy run. The ClickHouse-over-Iceberg p95 in particular spread run to run, anywhere from 1.16 to 4.05 seconds at the knee, which is what saturation looks like up close and is exactly why the claim is about where the knee sits and not how tall it is.

The part I keep coming back to is that even at the knee, none of these three crossed the lines that matter. The p95 at 64x ran roughly 2.7 to 3.8 seconds, which is over the sub-second floor an analyst would call snappy but still under the 10-second "flow" threshold where attention starts to break, and well under the 30-second "tolerable" line past which people give up and go make coffee. So the headroom here is large relative to any scheduled detection load a real SOC would put on a single host, and the inflection, when it finally comes, comes gracefully enough that you would notice it as a slowdown rather than an outage.

The caveat that travels

The ordering is portable, the coordinates are not.

I want to be honest about how far this number reaches, because the temptation with a clean knee at 64x is to quote it like a spec, and it is not one. This is a single host with a fixed cpuset and a particular corpus, so the absolute coordinate, that 64x, is bound to those choices and would not survive being copied onto a different machine with a different split and a heavier dataset. A larger corpus or heavier scheduled shapes moves the knee left, probably substantially, because the contention that produces it is throughput-determined and a bigger workload reaches saturation sooner. What travels from this bench is the ordering of the engines and the shape of the failure, the fact that these columnar/MPP engines stay flat and then inflect sharply rather than degrading linearly, and that the inflection is a scheduler- saturation event you can see coming in the utilization counter. The exact step where it happens is yours to measure on your own host.

That distinction is the whole reason I prefer a breaking-point bench to a winner bench. A winner bench tells you which engine posted the lowest number in a quiet room, which is the least operationally useful fact you can collect, while a breaking-point bench tells you the shape of the cliff and roughly where it sits, which is what you actually plan capacity against. The number you carry home is that this class of engine holds flat under heavy co-tenant load and then knees, so size for the knee and leave margin.

Why isolation

The knee is the failure a dedicated deployment is built to avoid.

Once you see the load on the right axis, the case for an isolation-first platform stops being an aesthetic preference and turns into a capacity argument. If interactive and scheduled work share a host, then every analyst hunt is competing for the same cores as the detection suite, and the headroom between you and the knee is a shared budget that someone else's scheduled job can spend without asking. When you isolate the interactive path onto its own deployment, the guarantee you are buying is that the foreground experience stays yours alone, because no scheduled backlog elsewhere can quietly walk you up toward an inflection you did not provision for.

This bench is one way of stating why keeping interactive serving off heavy batch and scheduled compute is a standing architectural choice rather than a tuning afterthought, particularly for a SOC that lives with steady, always-on detection schedules, the kind of load this bench is meant to model.

The benchmark's good news is that the engines have more tolerance for company than I assumed, since three of them rode 32x of co-tenant scheduled load with the interactive p95 barely moving, so isolation is not always mandatory and a small or moderate SOC may well be fine sharing a host. The benchmark's warning is that the tolerance is finite and the boundary is a knee rather than a gentle slope, so the moment your scheduled load grows, or your corpus does, or your shapes get heavier, the margin you were relying on shrinks and the inflection arrives sooner than the flat early steps would have led you to guess. Isolation-first is the posture that makes that arrival a non-event, because the job that would have spent your headroom is running somewhere you do not have to share.

On cost

What isolation costs, directionally.

I am not going to put a TCO multiple on isolation, because I do not have a measured one and the figures that float around for "dedicated versus shared" tend to come from vendor decks rather than benches. Directionally, and only directionally, an isolated interactive deployment costs more in standing infrastructure than co-locating everything on one cluster, because you are provisioning a path that sits underused whenever the analysts are quiet. What you get back is harder to put on a spreadsheet: the absence of the afternoon where a scheduled backlog turned every hunt into a thirty-second wait, the analyst hours not lost to a slow console, the incident not investigated slowly because the platform chose that moment to inflect. Whether that trade pays depends on how much scheduled load you actually run and how much an interactive stall costs your team, which is exactly the sort of thing you should size against your own knee rather than against a borrowed ratio. Treat any number you have seen for the cost of isolation, including the absence of one here, as illustrative until you have measured your own.

Takeaways

What to carry home.

  1. Benchmark the axis that hurts. Co-tenant scheduled load is what breaks the interactive experience, so a single-query-bigger-corpus chart misses the failure mode that actually shows up in production.
  2. These engines have real headroom. ClickHouse native, ClickHouse over Iceberg, and StarRocks held interactive p95 flat through 32x scheduled load on a single host before inflecting, and even at the 64x knee the p95 stayed under the 10-second flow line.
  3. The boundary behaves like a knee rather than a gentle slope, and the early flat steps give no warning, so plan for a sharp inflection and watch the utilization counter, which climbs a step ahead of the latency.
  4. Port the shape, not the coordinate. The 64x figure rides with this host, cpuset, and corpus; a larger corpus or heavier shapes moves it left, so measure your own knee and size to it.
  5. What isolation buys is a guarantee rather than raw speed, because a dedicated interactive deployment keeps a scheduled backlog elsewhere from spending the headroom you provisioned, which is the failure the knee represents.