Constrained Environments¶
Single-board-computer clusters and small cloud VPSs share one trait: a few GB of RAM and nothing to spare. A scan is CPU-light but memory-bursty: go test -coverprofile compiles the target repo's test binaries in parallel (Go's default -p = CPU count), and each compile can take 1–2 GB. A large repo on a 3.7 GB node — or a 2 GB VPS — can OOM the pod, and when the worker shares a node with the control plane, the whole cluster goes down with it.
go-crap-tracker is built to run in environments like this. This page explains the knobs and what they do.
What the system does by default¶
- Per-pod memory limit — worker pods run with a hard limit (3000Mi in
infra/), so one scan cannot eat a node's whole RAM. - Workers on dedicated nodes — the worker deployment pins workers to the worker pair (node affinity) and keeps them off the control-plane node and the node running the control app, so a scan's memory burst never competes with NATS, Redis and etcd.
- Default parallelism — a repo with no override runs
go testwith Go's default parallelism. That is the fast setting, and it is the right one for small and medium repos on any hardware.
The per-repo knob: go_flags¶
go_flags is a per-repo GOFLAGS value applied to that repo's go test and go-crap subprocesses:
go-crap-tracker repo config set https://github.com/microsoft/typescript-go \
--go-flags "-p=1 -parallel=2"
-p=1— onego testpackage at a time (one compile in flight).-parallel=2— caps per-test parallelism within a package.
Empty (the default) means "no GOFLAGS, Go's default parallelism" — fastest, and correct for most repos. Only a repo that actually OOMs (or nearly does) on your hardware needs a value; start at -p=1 -parallel=2 on a ~4 GB node and go lower, not higher.
Semantics:
- The value applies only to that repo's scans; other repos are unaffected.
- A per-repo
go_flagsoverrides any pod-levelGOFLAGSenvironment variable — the worker drops the inheritedGOFLAGSbefore applying the repo's value, so the per-repo setting always wins. - It is a per-repo override like
timeoutortest-args:repo config setis a partial upsert,repo config rmclears it.
Pod-level GOFLAGS (blanket fallback)¶
The worker deployment may set a GOFLAGS environment variable, which applies to every scan that has no per-repo value. Use it as a transition fallback or when every repo in your fleet is large; prefer per-repo go_flags once you know which repo needs it — a blanket -p=1 slows small repos down for nothing.
Sizing guide¶
| Hardware | What fits |
|---|---|
| ≥ 8 GB node, worker-dedicated | Large repos at default parallelism; usually no tuning needed |
| ~4 GB SBC node (e.g. a 4-node cluster of 3.7 GB boards) | Large repos need -p=1 -parallel=2; small repos are fine at defaults |
| 1–2 GB VPS | Small repos only; even -p=1 may be too much for the largest (10k+ function) repos — exclude them, or scan them from a bigger box |
Observed on a 3.7 GB node: a single compile burst peaks around 2.1 GB RSS; with -p=1 -parallel=2 a 14k-function repo (typescript-go) completes its full scan — tests, coverage, analysis — under the 3000Mi pod limit without OOM.
Cold build cache matters for timeouts. go test first compiles every test binary (that is the memory- and time-heavy part), then runs the tests. On this hardware a cold-compile typescript-go run takes over 30 minutes — too long for the default cache.test_timeout — while a warm-cache run of the same repo finishes in about 6. So a large repo's per-repo timeout should cover its cold compile (typescript-go runs with --timeout 60m), not its warm time. A cold-cache first attempt that hits the timeout simply retries and succeeds warm; the timeout headroom makes even that unnecessary.
Symptom → fix¶
| Symptom | Fix |
|---|---|
| Worker pod OOMKilled mid-scan | Set --go-flags "-p=1 -parallel=2" on that repo; raise the pod limit only if the node has the RAM |
| Whole node reboots / control plane goes down | Pin workers off the control-plane node (node affinity or taints); set per-repo go_flags |
| A repo scans fine on big hardware, OOMs on your cluster | That is the repo, not the cluster — go_flags is the per-repo valve |
Related¶
- Repo Cache — per-repo override reference (ref, test-args, go-flags, timeouts).
- Deployment — worker scheduling, limits, image.
- repo command —
repo config set --go-flags.