UPDATED · 17 JUN 2026 · EDIT ON GITHUB
ARCHITECTURE · DETECTION PIPELINE

The detection pipeline.

Every event passes through the same five-stage pipeline. Each stage is a separately scaled microservice; back-pressure is monitored and exposed via /v1/health/streams.

The five stages

STAGE 1
Decode & parse
Native format → canonical event.
STAGE 2
Enrich
Asset · identity · geo · intel.
STAGE 3
Evaluate
Streaming detection plans.
STAGE 4
Correlate
Window joins on entity_id.
STAGE 5
Decide
Case · contain · suppress.
FIGURE 2 · PER-STAGE LATENCY (p50)

Detection-as-code

Detections are declarative plans, versioned in git and shipped through CI like any other code — not rules typed into a console. A plan says what to match, how to correlate, and what to do; the pipeline compiles it into a streaming query.

DETECTION PLAN · winrm-burst.yml
plan: lateral-movement/winrm-burst
severity: high
match:
  type: endpoint.process
  where: cmd ~ "wsmprovhost" and parent != "services.exe"
correlate:
  by: entity.target
  window: 5m
  threshold: 3
emit:
  case: "WinRM lateral movement on $target"
  contain: [isolate-host, revoke-sessions]

Plans are evaluated continuously against the live stream and can be back-tested over history before promotion: td detect test winrm-burst.yml --since 30d.

Latency budget

StageWorkp50p99
Decode & parseNative format → canonical event25 ms70 ms
EnrichAsset, identity, geo, intel joins40 ms110 ms
EvaluateStreaming detection plans90 ms240 ms
CorrelateWindow joins on entity_idwindowed
DecideCase · contain · suppress<10 ms30 ms

Backpressure & health

Each stage is scaled independently. Per-stream lag and backpressure are exposed so you can alert before a slow source masks a detection:

$ td health streams
{
  "endpoint.process": { "lag_ms": 180, "backpressure": false },
  "identity.signin":  { "lag_ms": 240, "backpressure": false },
  "network.flow":     { "lag_ms": 910, "backpressure": true  }
}
← PREV Data Fabric NEXT → Response Engine