Continuous profiling for code-level performance in production
Always-on continuous profiling shows which functions consume CPU, memory and locks in production, with under 1% overhead and direct links to traces.Why teams use Continuous Profiling in Obseria
See the exact line of code
Go beyond service-level latency and pinpoint the functions and call paths that consume resources.
Cut compute cost
Find hot paths, inefficient serialization and excess allocations that inflate your cloud bill.
Safe for production
Sampling-based profilers run continuously with under 1% overhead, so you never need to reproduce an issue.
Continuous Profiling in three steps
- Step 1
Deploy the Obseria Agent
The agent, installed once per host, collects profiles for supported runtimes alongside metrics, logs and traces.
- Step 2
Profiles are correlated automatically
Each profile is tagged with service, version, host and pod, and linked to spans from the same time window.
- Step 3
Compare and optimize
Use flame graphs and diff views to compare versions, time ranges or hosts and verify each optimization.
Capabilities
- CPU and wall-clock profiles. Understand where code spends on-CPU time and where it waits on I/O, locks or downstream calls.
- Memory and allocation profiles. Find allocation hot spots, growing heaps and objects that put pressure on the garbage collector.
- Interactive flame graphs. Zoom, filter and search call stacks across services, hosts and versions.
- Differential profiling. Compare two versions or time ranges to see exactly which functions got slower after a deployment.
- Span-to-profile linking. Open the code-level profile behind a slow span with one click.
- Kubernetes-aware labels. Slice profiles by namespace, workload, pod and node, enriched automatically by Obseria Pipeline.
Continuous Profiling: what you need to know
What is continuous profiling?
Continuous profiling is the practice of collecting performance profiles from applications running in production, all the time, instead of attaching a profiler only when something goes wrong. A profile is a statistical sample of stack traces: at regular intervals the profiler records which function is executing, how much memory is allocated or which thread is waiting. Aggregated over time, these samples show precisely where an application spends its resources.
Traditional profilers are heavy and used locally or in staging. Continuous profilers are designed for production: they rely on low-frequency sampling, efficient stack unwinding and compact storage, so they can run on every instance with minimal impact.
Why continuous profiling matters
Metrics tell you that CPU is at 80 percent; traces tell you that a span took 900 milliseconds. Neither tells you which line of code is responsible. Continuous profiling closes that gap and adds a fourth signal next to metrics, logs and traces.
- Faster root cause: when latency regresses, you see the function that changed instead of bisecting commits.
- Lower infrastructure cost: small inefficiencies in hot paths are multiplied by every request and every replica. Profiles make them visible.
- No reproduction needed: intermittent issues, such as a slow code path that only triggers for some tenants, are captured when they happen.
- Better capacity planning: knowing what consumes CPU and memory helps you size workloads and set realistic limits in Kubernetes.
Profile types and what they reveal
| Profile type | What it shows | Typical finding |
|---|---|---|
| CPU | Time spent executing on CPU per function | Expensive JSON serialization or regex in a hot loop |
| Wall clock | Total elapsed time including waiting | Blocking I/O or synchronous downstream calls |
| Allocations | Where memory is allocated and how much | Excessive short-lived objects causing GC pressure |
| Heap | Memory currently in use | Leaks and unbounded caches |
| Locks and contention | Time threads wait on mutexes | A shared lock that serializes concurrent requests |
Which types are available depends on the runtime. The flame graph is the standard visualization: width represents the share of samples, and the call stack grows from the bottom up.
How Obseria does continuous profiling
The Obseria Agent collects profiles alongside metrics, logs, traces and security signals, so there is no extra profiler to roll out. Profiling runs with under 1% overhead. Profiles are stored in Obseria Lake and labeled with service, version, host, container and Kubernetes metadata, which makes it possible to filter and compare across any dimension.
The key difference is correlation. Because Obseria also holds your distributed traces, you can open a slow span and see the profile samples captured on the same instance at the same time. Obseria Intelligence uses profiles as evidence in root-cause investigations, for example to show that a latency regression after a release is caused by a new code path in a specific function. Differential flame graphs compare two versions side by side, so you can confirm that an optimization actually saved CPU before rolling it out everywhere.
Profiles also feed cost work. By aggregating CPU samples across all replicas of a service, you can estimate which functions account for the largest share of compute time and focus optimization effort where it reduces infrastructure spend the most, rather than on code that only looks slow in isolation.
Best practices for continuous profiling
- Profile everywhere, not just in staging. Production traffic patterns and data volumes rarely match test environments.
- Tag profiles with version information so every deployment can be compared with its predecessor.
- Start with the widest frames. In a flame graph, optimize the functions that take the largest share of samples first.
- Combine CPU and allocation profiles. High CPU in the garbage collector is usually an allocation problem.
- Review profiles regularly, not only during incidents. A monthly look at top consumers often yields significant cost savings.
- Link profiling to SLOs. Prioritize optimizations on endpoints that threaten latency objectives.
Frequently asked questions
Obseria's continuous profiling runs with under 1% overhead because it uses low-frequency statistical sampling rather than instrumenting every function call.
Tracing shows how a request flows between services and how long each step takes. Profiling shows which functions inside a process consume CPU, memory or wait time. Obseria links both, so you can move from a slow span to its code-level profile.
No code changes are required for supported runtimes. The Obseria Agent collects profiles automatically once it is installed on the host or deployed to your Kubernetes cluster.
Yes. Differential flame graphs compare two versions, hosts or time ranges and highlight functions that became more or less expensive.
Yes. Every Obseria feature is included in usage-based pricing. You can try continuous profiling in the 14-day free trial without a credit card.
Ready for observability that delivers answers?
Try every feature free for 14 days, no credit card and no proprietary agents.