CPU and memory profiles usually get pulled manually, after something is already on fire. Continuous profiling keeps them running in the background for free.
The typical profiling workflow is reactive: something is slow, someone runs pprof by hand, captures thirty seconds of data, and hopes the problem happened to occur during that window. Continuous profiling removes the timing gamble by sampling constantly at low overhead and keeping history to query later.
1. Add the profiler alongside existing instrumentation
The Helix Go SDK ships a profiler package that runs on its own goroutine and samples at a low, fixed rate designed to stay under one percent CPU overhead in steady state.
import "github.com/helix-obs/sdk-go/profiler"
func main() {
profiler.Start(profiler.Config{
Service: "pricing-service",
ProfileTypes: []profiler.Type{profiler.CPU, profiler.Heap},
})
// existing main() logic unchanged
}2. Correlate a profile with a specific slow trace
The real value shows up when a profile can be scoped to the exact time window of a slow request, rather than a generic five-minute average across all traffic.
from profiles
| where service.name == "pricing-service"
| where timestamp between (trace.start_time, trace.end_time)
| where profile.type == "cpu"
| top 10 by self_time3. Compare before and after a deploy
Because profiles are continuous rather than one-off snapshots, comparing CPU time by function across two deploy versions is a straightforward filter rather than a manual before-and-after capture.
from profiles
| where service.name == "pricing-service"
| where deployment.version in ("v412", "v413")
| summarize sum(self_time) by function, deployment.versionA function that jumps from a small share of total CPU time to a dominant one between two adjacent versions is usually the fastest way to catch a performance regression before it shows up as a latency alert three days later.
4. Keep retention shorter than traces
Profile data is bulky relative to traces. A retention window of seven to fourteen days is usually enough, since profiling is almost always used to investigate something recent, not to answer a question from three months ago.
- Add the profiler at startup, the same low-overhead pattern as trace and metric setup.
- Scope profile queries to the time window of a specific slow trace for precise answers.
- Compare CPU time by function across deploy versions to catch regressions early.
- Set a shorter retention window for profiles than for traces, recent history is what matters.