TrueWatch
Get Started

What Is Continuous Profiling? A Guide to OpenTelemetry Profiles in 2026

Oct 23, 2026

Continuous profiling is the practice of recording where your code spends CPU time and memory, all the time, in production, with low enough overhead to leave it running. Instead of attaching a profiler after an incident starts, you keep a running record of every service and look back at the exact functions and lines of code behind a slowdown.

In March 2026, the OpenTelemetry project announced that its Profiles signal had entered public alpha. That puts profiling on a path to sit alongside metrics, logs, and traces in the same open standard. This guide explains what continuous profiling is, how it works, what the OpenTelemetry Profiles alpha changes, and how to run profiling in production today.

What is continuous profiling?

A profiler samples the call stacks of a running program and counts how often each function appears. Traditional profiling is done on demand: a developer runs a profiler on a laptop or attaches one to a server for a few minutes. Continuous profiling does the same thing across your whole fleet, all the time, and stores the results so you can query any service for any time window.

The other signals tell you that something is slow and where in the request it happened. Profiles tell you why at the code level:

SignalQuestion it answers
MetricsIs latency or CPU usage going up?
LogsWhat did the application say happened?
TracesWhich service and which call in the request took the time?
ProfilesWhich function, and which line of code, used the CPU or memory?

A trace can tell you a database call took 800 ms. A profile can tell you the 800 ms was spent serializing a response in one function you did not expect to be expensive.

How continuous profiling works

Most continuous profilers follow the same four steps:

  1. Sample. The profiler captures stack traces at a fixed rate, often around 100 samples per second for CPU profiles. Sampling, rather than instrumenting every function call, is what keeps overhead low.
  2. Aggregate. Identical stacks are merged and counted, so a minute of samples compresses into a compact profile.
  3. Upload. An agent sends profiles at a regular interval, usually every few seconds to a minute, tagged with service, host, version, and environment.
  4. Analyze. The backend stores profiles over time and renders them as flame graphs you can filter, compare, and link to other signals.

There are two common ways to collect profiles:

  • Language profilers run inside the application runtime, for example async-profiler for Java, py-spy for Python, and pprof for Go. They understand the runtime well and can capture memory allocations, locks, and other runtime-specific data.
  • eBPF-based profilers run in the Linux kernel and profile every process on a host without code changes. They are a fast way to get broad coverage, especially for compiled languages.

Common profile types

Different profile types answer different questions. Start with CPU and add others as needed.

Profile typeWhat it measuresWhen to use it
CPUTime functions spend running on the CPUHigh CPU usage, slow compute paths
Wall time or off-CPUTime spent waiting on I/O, locks, or the networkRequests that are slow while CPU stays low
Heap or allocationMemory allocated and retained by each functionMemory leaks, frequent garbage collection
Lock or mutexTime threads spend waiting for locksContention under load
I/OTime spent on disk and network reads and writesSlow storage or downstream calls

How to read a flame graph

A flame graph is the standard way to view a profile.

flame graphprofile1_7160ae455e.gif

  • Each box is a function. The box below it is the function that called it.
  • Width is cost. The wider a box, the more samples (CPU time, memory, or wait time) it accounts for. The x-axis is not time order.
  • Look for wide plateaus. A wide box near the top of a stack is a function doing a lot of work itself. That is usually where to start optimizing.
  • Compare profiles. Comparing the same service before and after a deployment, or during an incident and a normal period, shows which functions changed.

What the OpenTelemetry Profiles alpha brings

On 26 March 2026, the OpenTelemetry project announced that Profiles had entered public alpha. According to the announcement, the alpha includes:

  • A standard profiling format in OTLP. It deduplicates stacks to stay compact, and pprof data can be converted to and from OTLP Profiles with no loss of information.
  • An eBPF-based profiler that now runs as an OpenTelemetry Collector receiver, so it can profile a whole Linux host with no code changes.
  • Links to traces. Profile samples can carry trace_id and span_id, so a slow span can lead straight to the code that made it slow.
  • Collector support. A pprof receiver, Kubernetes metadata through the k8sattributesprocessor, and OTTL support for filtering and transforming profiles.
  • Semantic conventions and conformance tooling for the most common profiling attributes, plus a checker that validates exported profiles against the specification.

The project is also clear about the limits. Because the signal is in alpha, it "should not be used for critical production workloads" yet, and production-ready backends for OTLP Profiles are still emerging. Beta and general availability are the next milestones.

Why OpenTelemetry Profiles matters for observability teams

Until now, profiling has usually lived in its own agent, its own format, and its own UI. OpenTelemetry Profiles changes three things over time:

  • One pipeline. Profiles can travel through the same OpenTelemetry Collector you already use for metrics, logs, and traces.
  • Shared context. The same resource attributes (service, version, Kubernetes pod) apply across all four signals, which makes correlation reliable.
  • Less lock-in. A vendor-neutral format means you can change backends without changing how you collect profiles.

How to use continuous profiling in production today

You do not have to wait for the OpenTelemetry signal to stabilize:

  1. Use a mature profiler for production now. Language profilers such as async-profiler (Java) and py-spy (Python), and pprof-based tools for Go, are widely used in production.
  2. Experiment with the OpenTelemetry eBPF profiler in staging, so you are ready when the signal reaches beta.
  3. Start with CPU profiles on the services behind your most important user journeys. Add memory profiles when you chase leaks or high garbage collection time.
  4. Tag every profile with service, version, and environment so you can compare deployments.
  5. Link profiles to traces. The value grows when you can jump from a slow span to its flame graph without searching.
  6. Measure the overhead on your own services before rolling out widely, and set sampling rates accordingly.

Continuous profiling use cases

  • Latency regressions after a release. Compare flame graphs from the old and new versions to find the function that changed.
  • Cloud cost reduction. CPU profiles show which code paths consume the most compute, so you can optimize the code that drives your bill.
  • Memory leaks. Heap profiles over time show which allocations keep growing.
  • Incident root cause. Because profiles are always on, the data from the incident window is already there when you start investigating.

What to look for in a continuous profiling tool

  • Low overhead, so it can stay on all the time
  • Support for the runtimes you actually run
  • Flame graphs you can compare over time and between versions
  • A direct link from traces to profiles
  • pprof compatibility today, and a path to OpenTelemetry Profiles

How TrueWatch handles continuous profiling

Continuous profiling is part of TrueWatch APM. Profiles are collected through DataKit, the TrueWatch collection agent, for languages including Python, Java, Go, and C/C++. TrueWatch measures the execution time, call relationships, and memory usage of functions and methods, and presents the results as flame graphs so you can find the functions and lines of code behind a bottleneck.

profile3_af2ca3bb57-Link Profile.gif

With Link Profile, TrueWatch correlates profiles with traces at the span level. From a slow request, you can open the code hotspots for that span in the same time period and see which method calls took the largest share of execution time.

Profiles are priced at $0.09 per 10,000 profiles per day, based on the volume collected by DataKit. See APM and Profiling pricing and the profiling documentation for setup details.

FAQ

What is continuous profiling?

Continuous profiling is the practice of recording CPU and memory usage at the function level in production, all the time, so you can find the exact code behind a performance problem after it happens.

What is the difference between profiling and tracing?

Tracing shows which service and which call in a request took time. Profiling shows which function and which line of code used the CPU or memory. Linking the two lets you move from a slow span to the code that caused it.

Is OpenTelemetry Profiles ready for production?

Not yet. It entered public alpha in March 2026, and the OpenTelemetry project advises against using it for critical production workloads until it reaches a more stable release.

Does continuous profiling slow down my application?

Continuous profilers, including eBPF-based ones, use sampling to keep overhead low so they can run in production. Measure the overhead on your own services before rolling out widely.

What is eBPF profiling?

eBPF profiling uses the Linux kernel's eBPF technology to sample stacks for every process on a host, with no code changes. OpenTelemetry now includes an eBPF profiler that runs as a Collector receiver.

How do you read a flame graph?

Each box is a function, and the box below it is its caller. Width shows how much CPU time or memory a function accounts for. Start with the widest boxes near the top of the stack.

Sources

Get in touch background

Get Started with TrueWatch