Validation tells you a pipeline is well formed. Simulation tells you what it produces. Shepherd stubs out every source in your pipeline with a synthetic one, redirects every destination to a capture harness, runs a real Alloy process against that rewritten config for a bounded window, and shows you the series and log lines that arrived.
There are three depths, and they answer different questions:
| Depth | Answers | Cost |
|---|---|---|
| Relabel / log preview | "What do my prometheus.relabel rules or loki.process stages do
to this input?" A per-rule, per-stage trace showing which rule dropped or rewrote a
label. |
Instant, in-process. |
| Flow check | "Is anything actually wired to a destination?" A static reachability pass that catches the component you added but never connected. | Instant. |
| Sandbox run | "If I ship this, what lands downstream?" A real Alloy process, synthetic sources, captured output, per-component health. | Bounded run (30s default), queued. |
In the visual builder, Flow check and Simulate sit next to Save in the toolbar; on narrower windows they move into the More actions menu. The relabel and log-preview traces land in the Simulation tab of the bottom drawer, beside Problems and Generated config; a sandbox run (Simulate › Sandbox run: a 30-second capture, about 45 seconds in all while Alloy flushes) opens in its own dialog, so you can keep editing while it goes. A run reports what was captured, the health of each component — a discovery or log source the sandbox replaced reads stubbed, not healthy — and a fidelity note naming which parts were stubbed rather than really executed — a green run against synthetic sources is a weaker claim than a green run in production, and the UI says so rather than letting you assume otherwise.
Match the window to the pipeline. A run observes for 30 seconds. A
prometheus.scrape with a 30-second scrape_interval may scrape once
or not at all in that time, so an empty result there says more about timing than about your
pipeline — shorten the interval for the simulation, or read the result with that in
mind.
What can be simulated, and by whom. A sandbox run takes a visual-builder graph, so a pipeline written as text, by a wizard or in git cannot be run (its graph view is read-only). Simulations need the org editor role: a member of a pipeline’s owning team who edits it in the builder below that role sees why Simulate is unavailable. One sandbox run executes at a time, a few more wait in a queue, and a run is refused when the queue is full.
The Helm chart ships it enabled by default — the chart auto-wires Shepherd's own config to the
chart's shepherd-simulator Service, so a plain helm install gets a
working sandbox with no extra flags.
To turn it off for a deployment where you don't want it:
helm install shepherd oci://ghcr.io/procoduck/charts/shepherd --version 0.22.0 \
--set simulator.enabled=false \
--set existingSecret=shepherd-secrets
The sandbox runs the simulated Alloy as a child process of a dedicated
shepherd-simulator pod with a default-deny egress NetworkPolicy, a
read-only root filesystem, no service account token mount, and CPU/memory limits — every one
of those controls is asserted by the chart's own tests, and the default render is asserted to
ship the simulator with its NetworkPolicy, never without. Containment has been verified with
in-cluster probes (e2e/k8s/simulator_containment_test.go) that dial from inside
the sandbox pod and confirm the rest of the cluster is unreachable. Stated honestly: the
sandbox transform bounds what credentials a run can see, and the network policy bounds where
it can reach — that combination is what's been proven, not an absolute guarantee against
anything a pipeline's own relabeling could do at runtime. If a deployment's threat model
needs the sandbox off entirely, use the switch above. The other two simulation tiers (flow
check, relabel/log trace) are unaffected either way — they run in-process and work out of the
box.
Local dev keeps the sandbox opt-in on purpose (make dev-sim) — that's a
test-environment choice so the default make dev/make e2e paths
exercise Shepherd without the simulator, not a statement about the production default.
make dev-sim # boots the dev stack with the sandbox tier enabled