13

Pyroscope: Continuous Profiles as Code-Level Evidence

Source: Observability Platform source — section 13, “Profiles: Pyroscope as the Code-Level Signal”

The enterprise problem and today’s slice

Enterprise problem: Metrics show a service consumes more CPU and traces show slow requests, but neither identifies which functions allocate memory, contend on locks, or burn processor time across the fleet.

Whole-course context: The incoming evidence is a connected slow checkout trace whose payment span dominates latency; today tests whether local code resource use explains that symptom or can be ruled out.

Today’s slice: Collect, retain, compare, and query continuous profiles in Pyroscope while controlling overhead, labels, tenant access, and source-code symbol exposure.

End-of-day evidence: Produce a bounded before/after flame graph with a named hot function, or a falsifiable result showing CPU remained normal during the slow-trace window.

Still unsolved: Unified Grafana navigation, cross-signal identity governance, and the complete platform operating architecture remain deferred.

Customer use cases

Profiles without a hypothesis become attractive pictures that do not guide action. These use cases require a code-level explanation or an explicit negative result tied to a known service window.

Use case IDActorCustomer jobSuccess outcomeDenial or recovery evidence
D13-UC-01Performance engineerIdentify which checkout functions changed CPU or allocation cost after a releaseA comparison profile attributes a material delta to named functions and deployment versionsA rollback or fixed build removes the delta; a normal profile can falsify local CPU as the cause
D13-UC-02Observability platform operatorProvide low-overhead tenant-safe profiling with governed symbols and retentionOverhead stays within budget and authorized service/version queries return profilesUnauthorized tenant/service access is denied and collector failure is detected with an unaffected control

Actor-centred user stories

“Profiling enabled” does not prove useful resolution, acceptable overhead, or safe access. These stories demand measured deltas and negative-path evidence.

Story IDUse case IDsUser storyObservable acceptance conditions
D13-US-01D13-UC-01As a performance engineer, I want to compare checkout profiles before and after a release, so that I can name the function responsible for changed resource useIdentical time windows and load controls show function-level delta, version labels, sample counts, and a repeatable fix or falsifier
D13-US-02D13-UC-02As a platform operator, I want profile collection bounded by overhead and access policy, so that production diagnosis does not create a new reliability or code-disclosure riskCPU/memory overhead remains within objective, tenant denial succeeds, ingestion loss is alerted, and authorized queries remain available

End-to-end product flows

A flame graph can mislead when workloads or time windows differ, so the flow preserves comparable inputs from collection through remediation. The terminal evidence includes both the visible stack delta and the controlled conditions.

Flow IDUse case IDsPathTriggerNumbered stepsTerminal evidence
D13-FLOW-01D13-UC-01, D13-UC-02HappyEngineer selects checkout CPU profiles for equal pre/post-release windows1. Language agent or eBPF collector samples stacks.<br>2. Collector attaches canonical service/environment/version labels.<br>3. Pyroscope validates tenant and persists profile data.<br>4. Query frontend resolves the two windows.<br>5. Grafana renders comparison flame graphs.<br>6. Engineer verifies the hot function under controlled load.Query, windows, labels, sample counts, flame-graph delta, overhead, environment, and run ID
D13-FLOW-02D13-UC-01, D13-UC-02RecoveryCollector stops or a foreign tenant requests checkout profiles1. Ingest heartbeat or profile freshness fails.<br>2. Alert identifies the collection boundary.<br>3. Foreign request is denied.<br>4. Collector restarts and profile freshness recovers.<br>5. Authorized comparison repeats.Gap interval, denial response, recovered freshness, unaffected service metrics, and run ID

System design derived from the flows

Profiling agents run near production code, so collection overhead and symbol exposure are trust-boundary concerns rather than UI details. The design separates application sampling, collection policy, Pyroscope storage/query, and operator access.

Use case IDEntry pointResponsible servicesAuthoritative storeFailure evidence
D13-UC-01Grafana Pyroscope data sourceQuery frontend, query backend, metastore, object-store readers, flame-graph rendererPyroscope object storage and metadata indexEmpty comparison, mismatched labels/windows, missing symbols, query error, or non-repeatable delta
D13-UC-02Profiling agent/export endpointLanguage profiler or eBPF collector, Alloy, Pyroscope distributor/write path, tenant auth, freshness monitorVersioned collection policy, Pyroscope object storage, and evidence storeRefused profiles, stale freshness, overhead breach, tenant denial failure, or object-store error

Data model and ownership

Profile stacks can reveal proprietary symbol names and code paths, so ownership and deletion must be explicit. Pyroscope owns telemetry copies; the source repository and application runtime retain authority over code and business data.

Generated-application database: Not created in this slice — profiles, metadata, policies, and proof runs are sufficient telemetry state and must not become a business-data store.

Record or entityStore and ownerPrimary keyForeign key or opaque referenceTenant keyMaterial constraintLifecycle and deletionUse case IDs
Profiling-policy revisionGit/config store owned by platform operationsprofile_policy_shaNone — root policy revision has no parentorganization_idApproved profiler, interval, labels, symbol policy, and overhead budgetReview, deploy, roll back, retain audit history, then expireD13-UC-02
Profile seriesPyroscope metadata/object storage owned by profiling platformtenant_id/profile_type/label_fingerprint/timeOpaque service and deployment referencestenant_idBounded labels; service/environment/version semantics remain stableIngest, compact, retain, tombstone, and delete by tenant policyD13-UC-01, D13-UC-02
Stack sample aggregatePyroscope profile block owned by profiling platformprofile_block_id/stack_fingerprintForeign reference to profile seriestenant_idCounts preserve stack ancestry and profile unitsMerge into blocks, retain with series, delete with profile retentionD13-UC-01
Profile proof runPlatform evidence store owned by operationsprofile_run_idOpaque references to policy, queries, versions, and result digestorganization_idComparable windows/load plus denial and overhead observations are immutableCreate per experiment, retain for audit objective, then expireD13-UC-01, D13-UC-02

Profile types and interpretation

Choosing the wrong profile type answers a different question and can send remediation toward unrelated code. CPU profiles estimate where on-CPU samples occur; allocation profiles attribute allocation activity; heap profiles represent retained memory; mutex, block, wall-time, thread, or goroutine profiles depend on language/runtime support.

A wide flame box means more samples in that stack, not necessarily slow wall-clock latency for one request. Validate units, runtime support, sampling interval, symbolization, and load shape before comparing widths.

Pyroscope v2 and query practice

Architecture guidance that assumes v1 ingester disks is now stale for new deployments. Pyroscope v2 writes profile data directly to object storage and uses a metastore as the stateful metadata/index and compaction coordinator; consult the current deployment and migration documentation for production topology.

Query by stable, bounded labels such as service, environment, and version. Keep instance IDs and request IDs out of the main series identity unless a measured use case and cardinality budget justify them.

Key takeaways

Profiles complement request traces by aggregating where code spends resources over time. Keep these distinctions:

  • Traces explain one distributed request; profiles aggregate code-level resource use across a window.
  • Comparable flame graphs require equal load, labels, units, and collection policy.
  • A normal profile is useful negative evidence that can rule out local CPU or allocation regressions.
  • Collection overhead, symbol access, tenant isolation, and freshness require explicit tests.
  • New deployments should follow current Pyroscope v2 architecture documentation.

Checklist

A flame graph screenshot alone is not reproducible evidence. Complete these checks:

  • [ ] Chose and documented the profile type, unit, profiler, and sampling interval.
  • [ ] Measured profiler CPU and memory overhead against an objective.
  • [ ] Compared equal pre/post windows under controlled traffic.
  • [ ] Named a function-level delta or documented a falsified local-code hypothesis.
  • [ ] Proved trace-to-profile mapping preserves service, tenant, and time.
  • [ ] Proved tenant denial, freshness alerting, retention, and deletion.

Sources

Pyroscope v2 changes storage and component responsibilities, so current primary documentation is authoritative. These sources support the lesson: