Skip to content
You are: content adapts, same page
Reading:
for the whole page, adjustable section by section
Self-hosted single binary · OpenTelemetry · Open source AGPL-3.0

Spot the wasted I/O in your traces. Price it in energy and carbon.

Perf Sentinel catches N+1s, redundant calls, slow queries and fanout in your OpenTelemetry traces, as a CI quality gate or an OTLP daemon, then turns every avoidable I/O into energy and CO₂.

An open-source project stewarded by
the Institut du Numérique Responsable
CRITN+1 HTTPGET /api/cart/enrich12 calls → 1 11 avoidable calls, fixable at inventory/enrich.py:88. One finding from the demo below, Findings tab.
12 × GET catalog-svc/api/products/{id} · 110 ms · 1 needed, 11 avoidable
What happens
For a single cart, the service calls the catalog one product at a time.
What it costs
11 avoidable calls per request, and the endpoint lands in the critical I/O intensity band.
Where to fix
inventory/enrich.py:88
batch endpoint ?ids=…, 12 calls → 1
See the full trace →
Live demo:
Open in a new tabOpen the live demo ↗
HTML report or TUI, whichever you prefer. The Hub is optional but recommended.
The synoptic shows Perf Sentinel from the inside, from the map of environments down to the detection rules.
// the problem

Why Perf Sentinel?

I/O anti-patterns hit any app, monolith or microservices. In distributed systems one request cascades across several services, so the waste only shows up when you look at the whole trace.

Perf Sentinel reads the traces your app already emits (SQL, HTTP, broker publishes), whatever the language or ORM: it sees the queries they generate, without needing to know JPA or EF Core.

Each avoidable I/O is also priced in energy and CO₂, bottom-up and attributable to the code.

Prerequisite: your services send OpenTelemetry traces of their database, HTTP and messaging calls, or Datadog traces through an OpenTelemetry Collector.

Check your tracing first: a database or HTTP call recorded without its query or URL is skipped. A thin report can mean a clean app or thin instrumentation.

What it is not: a full APM, a continuous profiler, nor (for now) a standalone regulatory carbon accounting platform. See the comparison.

Maturity: beta, pre-1.0, so commands and configuration can still change. In production with one team since June 2026.

Required span attributes and setup by language

// what gets detected

Twelve I/O anti-patterns, at the protocol level

On the SQL and HTTP requests your services already emit, whatever the language or ORM.

Eight repetition and slowness patterns, by protocol:

SQL
HTTP
Messaging
N+1
The same template repeated at least 5 times within one trace, with different parameters (the same destination for messaging).
Same template, different parameters, at least 5 times per trace.
✓
✓
✓
Redundant
Identical call, identical parameters, same trace.
Same call, same parameters, within the same trace.
✓
✓
—
Slow
The same operation over 500 ms at least 3 times within one trace.
Same operation over 500 ms, at least 3 times.
✓
✓
✓
Example: the N+1 from the demoinventory-svc · GET /api/cart/enrich · 12 calls → 1
neededavoidable
BEFORE
GET /api/cart/enrich
CartService::enrich
GET …/products/1
GET …/products/2
GET …/products/3
GET …/products/4
GET …/products/5
GET …/products/6
GET …/products/7
GET …/products/8
GET …/products/9
GET …/products/10
GET …/products/11
GET …/products/12
12 HTTP calls · 11 avoidable~8 ms each, one after another, over 110 ms
AFTER
GET /api/cart/enrich
CartService::enrich
GET …/products?ids=1,…,12
CRITN+1 HTTPGET /api/cart/enrich
Fixable at inventory/enrich.py:88 with a ?ids=… batch endpoint. The same finding is in the demo, Findings tab.
1 HTTP call · 12 calls → 1post-fix duration not measured: it depends on the batch endpoint

Plus four structural patterns:

span 22 children

Excessive fanout

> 20 children
A single operation (span) has more than 20 child calls (SQL, HTTP…), parallel or not.A single operation triggers too many child calls, parallel or not.
ABC request 16 outbound HTTPacross the trace

Chatty service

> 15 outbound HTTP
A single user request triggers more than 15 outbound HTTP calls in total, even when spread across several parents. That is what sets it apart from fanout.Too many outbound HTTP calls for one request, across all parents. That is what sets it apart from fanout.
service A · SQL spans 10 at once

Pool saturation

≥ 10 concurrent SQL
At least 10 SQL queries from the same service in flight at the same instant in one trace. A likely sign of contention, inferred from overlapping spans, not from pool metrics.Too many concurrent SQL queries from one service, inferred from overlapping spans.
today · same parent ABC possible ABC serial

Serialized calls

≥ 3 sibling calls
At least 3 sibling I/O calls (same parent), on different templates, run one after another when they could run in parallel.Sibling calls run one after another when they could run in parallel.

Every finding carries: type, severity, normalized template, occurrences, source endpoint, suggestion, source location and GreenOps impact. In daemon mode, cross-trace correlation is added.

Every finding gives its severity, the template at fault, the source endpoint, a fix suggestion and its GreenOps impact.

// your stack

Works with your languages, frameworks and ORMs

Detection reads the protocol, so it works on any runtime that emits OpenTelemetry traces. The ones below also have a setup guide or fix hints written for them.

Languages
Frameworks& ORMs
Languages
Frameworks& ORMs
Setup guides by language →
// four ways to run it

1 binary, 2 modes, 4 ways to deploy

Your traces
OpenTelemetry SDK
OTel Collector
Datadog via Collector
mode batch
Captured traces
Same traces, same verdict.
TUIoffline HTMLSARIFdeterministic JSONexit 1 on threshold
Exploration
local, built-in demo
Batch CI
quality gate in the pipeline
mode daemon
Continuous OTLP stream
gRPC :4317 · HTTP :4318
Prometheus /metricslive dashboardquery APIcross-trace correlation→ Hub (history)
Sidecar
one daemon per service
Centralized
a single daemon, via a Collector

With an AI coding assistant

A plugin brings Perf Sentinel into the change you are working on. It asks before every change it makes.

Available today for Claude Code.

  1. before production/perf-sentinel:perf-tests

    Writes performance integration tests for your current change, runs them under Perf Sentinel and, if you agree, wires them into your CI.

  2. in production, with the Hub/perf-sentinel:prod-findings

    Reads your services’ findings from the Hub, ranks them by avoidable I/O and fixes them in small batches, each proved by a non‑regression test.

# in Claude Code
> /plugin marketplace add Institut-du-Numerique-Responsable/perf-sentinel-claude
> /plugin install perf-sentinel@perf-sentinel
The plugin on GitHub ↗

Published by the Perf Sentinel project, independent of Anthropic. Claude Code is an Anthropic product.

// built in rust

A single Rust binary, measured

Rust ≥ 1.99.1 (MSRV)

The figures below time the analysis pipeline alone (single-threaded, on synthetic datasets), so they isolate pipeline cost, not end-to-end throughput.

576k–⁠1.2M
events/s, pipeline throughput (GCP c3-standard-8 x86 to M4 Pro)
0.8–⁠1.9 µs
per event, p50 to p99
17 → 980 MB
daemon RSS: idle, then production median at ten times the default retention
Rust 2024
with a static musl binary and a FROM scratch image
Full benchmarks in the docs →
// one for the fleet

A C# Hub, for finding history

.NET.NET SDK 10.0.403

In daemon mode, Perf Sentinel holds findings in memory, oldest evicted first, and /api/findings answers at most 1,000 rows: current state, not history. The Hub, a separate service, collects from every daemon and keeps what an eviction or restart would erase, such as when a finding first appeared. It also receives the periodic reports a scheduled job publishes, checks them, renders their PDF and shares them under an expiring link. Its recap ranks what to fix first and what moved, in an engineering and a management view, and a confirmed fix becomes a signed share card.

In daemon mode, Perf Sentinel holds a bounded number of findings in memory: current state, not history. The Hub, a separate service, collects from every daemon and keeps what an eviction or restart would erase. It also checks and shares the periodic reports, ranks what to fix first in a recap for engineers and management, and signs share cards.

perf-sentinel · daemon 1
perf-sentinel · daemon 2
perf-sentinel · daemon 3
bounded memory, oldest evicted first
push + retry
fallback pull (the Hub polls)
Perf Sentinel Hub
Keeps the finding history, including the first-seen date, which survives:
a restartan evictiona template change
BrowserLAUNCHER
picks a source and the run settings
the Hub runs Perf Sentinel, then serves the dashboard
~130 ms
cold start to first response (median, arm64 image)
cold start
~21 MB
RSS at rest, before any import
RSS at rest
38–⁠40 MB
compressed image (Hub ~11 MB, Perf Sentinel ~7 MB, chiseled base ~21 MB)
compressed image
NativeAOT
one native executable, no .NET runtime, chiseled non-root image
native executable, no .NET runtime
// the team review

What to fix first, down to the line of code

For the team review, the Hub ranks findings by avoidable I/O over the period and gives each one its fix, its place in the code and its signature. Trends count closed days only. No AI writes it: every sentence comes from the engine’s rules.

The recap, engineering viewMonth of July 2026 · production
What to fix firstranked by avoidable I/O
  1. 1
    N+1 SQLShowing a cartshopGET /cart/{id}

    Use WHERE ... IN (?) to batch 41 queries into one

    1.9 millionavoidable I/Omore than in June
    How to fix
    SELECT * FROM cart_item WHERE cart_id = ?
    Suggested fixjava_jpa

    Use JOIN FETCH on the relationship or annotate the repository method with @EntityGraph to load associations in a single query.

    Where in the code
    CartItemRepository.findByCartId
    shop/src/main/java/acme/cart/CartItemRepository.java:31
    detections
    1,284
    confidence
    daemon_production
    signature
    n_plus_one_sql:shop:GET__cart_{id}:09908701485122dcb9d5d84b7c653b7c
  2. 2
    N+1 messagingConfirming an ordercheckoutPOST /orders/{id}/confirm

    Send 12 messages as one batch instead of one publish per item

    412,000avoidable I/Onew this month
  3. 3
    Redundant HTTPOpening the settingsaccountGET /api/settings

    Identical operation executed 3 times: cache result or deduplicate

    96,000avoidable I/Ofewer than in June
Recap adapted from the Hub demo, fictional company.
// the blind spot

The carbon weight of digital,
and its blind spot: application code

Digital already accounts for 1.8% to 3.9% of global greenhouse-gas emissions, on par with civil aviation and growing fast. But the share driven by bloated, poorly optimized code and web apps stays unquantified at scale.

Digital is 1.8% to 3.9% of global GHG
5 %4 %3 %2 %1 %0 %
1.8%
3.9% (incl. ? %)
?
Low estimate
High estimate
Measured: data centers, networks, devices
Unmeasured zone: heavy, poorly optimized web apps
Code is missing from the numbers

Published estimates cover data centers, networks and devices. None of them goes down to a single query or endpoint.

72%
reduction in emissions per visit after Jisc optimized one high-traffic page on the front end (1.09 g → 0.30 g CO₂)
// estimate bottom-up, not top-down

Perf Sentinel’s bottom-up approach against the top-down of current tools

Top-down approach
Current IT and carbon tools
•A share of averages: data-center draw, sector ratios.
•Estimates a global footprint from the cloud bill or headcount.
•Gives a yearly number, but not the detail of what weighs.
Result
A global figure, not attributable and not actionable.
Bottom-up approach
Perf Sentinel on heavy web apps
✓Observes the real application, query by query.
✓Translates each operation into energy then carbon, following the SCI method.
✓Pinpoints avoidable waste and its cost.
Result
A quantified hotspot, attributable to the code and directly actionable.
// greenops

Every avoidable I/O has a cost,
in time, energy and carbon

Cutting N+1s and redundant calls improves response times and energy use at the same time. co2.total follows the Software Carbon Intensity v1.0 numerator (ISO/IEC 21031:2024): energy used (E) times the electricity grid carbon intensity (I), plus embodied hardware emissions (M), summed over the analyzed traces.

Cutting N+1s and redundant calls improves response times and energy use at the same time. co2.total follows the Software Carbon Intensity v1.0 method (ISO/IEC 21031:2024), summed over the analyzed traces.

co2.total
Energy
estimated per I/O, or measured in daemon mode
Carbon intensity
per region, embedded table or Electricity Maps
Embodied
hardware share, per request
low and high bounds in every report
co2.avoidable: the share due to avoidable I/O, embodied excluded

I/O intensity score (IIS)

An endpoint's total I/O operations divided by its number of invocations.

I/O waste ratio

Avoidable operations over total operations, the directly recoverable share.

Multi-region co2.total

SCI v1.0 numerator, automatic per-region scoring when spans carry cloud.region.

Directional estimate, enough to prioritize and compare before and after. A measured energy sourceA measured energy source (daemon mode) sharpens E. Activity data for Watershed · Sweep · Greenly · Persefoni, or RGESN work. Also emits periodic public energy and carbon reports (quarterly or yearly, as JSON and PDF/A-3b, optional Sigstore signature, hash-verifiable).

A directional estimate, enough to prioritize and compare before and after. A measured energy source sharpens it. It also serves as activity data for your carbon tools or RGESN work, and can be published as a periodic report.

// measurement sources

From estimate to measurement,
where your infrastructure allows it

By default, energy is estimated from I/O: a directional figure, within 2×. In daemon mode, it can come from a measurement, with the grid’s live carbon intensity. The JSON report names its source.

energy, depending on your infrastructure
Software measurement: CPU (RAPL)
One of the three, Alumet first. Needs Linux x86 with RAPL access: bare metal, or a VM that exposes it (rare in the cloud).
Recommended
Attributes RAPL energy per container. Can also measure a self-hosted database or broker.
per container
Attributes RAPL energy per process.
per process
Attributes RAPL energy per container or per process. Built for Kubernetes, without requiring it.
per container or process
Whole-server measurement
Physical servers whose BMC you can reach, any CPU architecture
Power of the whole server, read from its controller (BMC): fans and disks included. Cloud VMs expose no BMC.
Cloud VMs expose no BMC.
Bare metal · BMC
live carbon intensity

Replaces the built-in carbon intensity with the live value for the zone your services run in, the biggest lever on gCO₂ where the electricity mix varies.

Grid operatorsFree
The value the zone’s grid operator publishes, straight from the source.
FR
RTE
éCO2mix
GB
NESO
Carbon Intensity API
FI
Fingrid
Open Data
DK
Energinet
Energi Data Service
ES
REE
e·sios
AU
Open Electricity
NEM · WEM
HU
MAVIR
export XLSX
NZ
em6
Transpower
Live intensity for most zones worldwide, on a life-cycle basis.
API keypaid for commercial use

Independent of the energy source: it combines with any option above, or with the default estimate. Where both cover a zone, Electricity Maps wins. Where neither covers it, the built-in table applies.

Software measurement is not a power meter: RAPL sees only CPU and memory, roughly half to two thirds of wall-plug draw. Only Redfish also sees fans, disks and network cards.

Measurement sources and precision in the docs →
// how it compares

Lightweight, agnostic, CI-native, carbon-aware

Capability
Typical commercial APM
Perf Sentinel
Runtime footprint
Agent per host or inside each service (~130 MB RSS for the Datadog Agent)
One daemon for the whole fleet, 17 MB idle, then sized by the findings it retains
Language coverage
Per-language agents or SDK
Any OTel-instrumented runtime
N+1 SQL & HTTP detection
Yes, agent-bound
Yes, protocol-level
Cross-service correlation
Yes
Yes, via trace ID
Native CI quality gate
No gate on trace anti-patterns
Yes, exit 1 on threshold
GreenOps score (IIS, waste ratio)
No
Built-in
Per-span carbon attribution
No
Yes (SCI-aligned, directional)
License & hosting
Proprietary SaaS, usage-based
AGPL-3.0, fully self-hostable

‘Typical commercial APM’: agent-based SaaS tools such as Datadog and New Relic, varying by product. The agent figure, published by Datadog for Agent 7.34, excludes the per-service tracer, as Perf Sentinel’s excludes the OTel instrumentation it reads. Not a full APM: it runs alongside an observability suite, not instead of it. Per-tool comparison (Sentry, Hypersistence, Digma, Pyroscope, OTJAE) in the docs.

‘Typical commercial APM’: agent-based SaaS tools such as Datadog and New Relic. Perf Sentinel runs alongside an observability suite, not instead of it.

What Perf Sentinel is not

✗Not a full APM replacement. It has no RUM, no log aggregation and no alerting UI, which Datadog, New Relic and Sentry cover.No RUM, no log aggregation, no alerting.
✗Not a continuous profiler. It watches I/O patterns rather than CPU time or allocations, and pairs well with Grafana Pyroscope.It watches I/O, not CPU time or allocations.
✗Not a monitoring platform. A daemon keeps a bounded ring of recent findings, and Perf Sentinel Hub adds the history across a fleet.The daemon keeps recent findings, the Hub the history.
✗Not (yet) a standalone regulatory carbon accounting platform. Standalone CSRD or GHG Protocol Scope 2/3 reporting needs third-party verification it does not have. Scope and pairings:It lacks the third-party verification CSRD or GHG Protocol reporting needs. Scope: see the GreenOps section.
✗Not a replacement for measured energy. The I/O-to-energy model is a directional estimate, refined by Alumet, Scaphandre, Kepler, Redfish or cloud energy APIs. What software-only attribution covers:A directional estimate that a probe refines. What it covers: see the limitations docs.
✗Not zero-config. Protocol-level detection requires OTel instrumentation in your apps.It needs OTel instrumentation in your apps.
✗Not an IDE plugin. For in-IDE feedback on JVM/.NET code as you type, Digma offers a well-integrated JetBrains experience.No feedback as you type in the editor.
// publish and verify

A report anyone can check

The daemon archives every analysis window. perf-sentinel disclose turns them into a quarterly or yearly report, and disclose-pdf renders it as a PDF/A-3b. The Hub can receive and share it, but nobody needs it to verify one.

First page of the sample report: energy 18.42 kWh, carbon 1.91 kgCO₂eq, avoidable 0.34 kgCO₂eq for the first quarter of 2026.

A ten-page PDF anyone can read without a tool: the quarter’s figures and their uncertainty, the scope measured, the limits of the method, and an annex of every field in the report. The source report and its signature travel as attachments, and one command rechecks all of it.

  • PDF/A-3b
  • 10 pages
  • signed (Sigstore)
  • fictional company

Verify it yourself

After the download, one command recomputes the hash of the attached report, checks that the attestation names it and checks the signature, with cosign on the PATH.

One command, with cosign on the PATH, recomputes the hash of the attached report and checks its signature.

$ curl -fsSLO https://perf-sentinel.dev/exemple/disclosure/report.pdf
$ perf-sentinel verify-hash --report report.pdf \
$ perf-sentinel verify-hash --report report.pdf
--expected-identity https://github.com/Institut-du-Numerique-Responsable/perf-sentinel/.github/workflows/sample-disclosure.yml@refs/heads/main…/sample-disclosure.yml@refs/heads/main \
--expected-issuer https://token.actions.githubusercontent.com
Overall: TRUSTED
// license

AGPL-3.0, and what it means for your code

open source

A legal-team-friendly summary, no repository digging needed. Perf Sentinel is licensed under the GNU Affero General Public License v3.0.

✓
Your services stay yours

Running Perf Sentinel does not place your own services under AGPL. It is a standalone process: your applications only send it OpenTelemetry traces over the network (OTLP), a remote communication and not a compile-time link, so it creates no derivative work and imposes no licensing obligation on your code.

✓
Unmodified binaries, no obligation

The AGPL covers Perf Sentinel’s own source code. Using the official binaries or container image unmodified triggers no copyleft obligation of any kind.

The one condition: if you modify Perf Sentinel and offer the modified version to third parties over a network, article 13 requires you to make that modified source available to those users. This is a practical summary, not legal advice. Consult your legal team if in doubt.

The one condition: if you modify Perf Sentinel and offer that version to third parties over a network, article 13 requires you to publish its source. A practical summary, not legal advice.

// for your security team

What your security team will check, and where to find it

Perf Sentinel and its Hub install on your infrastructure, no SaaS. What a security review usually covers: on by default, or left to you.

DATA

Queries normalized in memory

The engine replaces SQL values and URL identifiers with placeholders in memory, with documented exceptions. The Hub keeps these findings 180 days by default, in a SQLite database on your side.

SQL values and URL identifiers replaced, with documented exceptions. The Hub keeps findings 180 days by default, on your side.

FLOWS

No telemetry

The engine only reaches what you configure, such as an energy measurement source. The Hub checks GitHub once a day for the latest version, and one setting turns it off.

The Hub checks GitHub once a day for the latest version, and one setting turns it off.

ACCESS

What is open, and how to close it

The daemon listens on 127.0.0.1 by default, TLS optional. Its reads are not authenticated: a NetworkPolicy or your ingress filters them. The Hub requires a key per source and can put its UI behind your SSO.

The daemon’s reads are not authenticated: a NetworkPolicy or your ingress filters them. The Hub requires a key per source.

CODE AND IMAGE

Rust without unsafe, rootless images

The engine’s core forbids unsafe code at compile time. Both images run without root, FROM scratch for the engine and chiseled for the Hub, read-only in their Helm charts.

FROM scratch for the engine, chiseled for the Hub, read-only in their Helm charts.

SUPPLY CHAIN

Signed tags, traceable binaries

Signed release tags, build provenance attested through Sigstore and an SPDX SBOM with every version. Actions pinned by SHA, dependencies audited daily.

Build provenance attested through Sigstore and an SPDX SBOM with every version.

REPORTING

Private reporting, published response times

Vulnerabilities are reported privately through GitHub. Each repository publishes its response times and the versions that receive fixes.

Each repository also publishes the versions that receive fixes.

The full security overview →

Put the sentinel in your pipeline

Built-in demo with nothing to install on the app side, then a quality gate on captured traces or an OTLP daemon beside your tracing.

# 1. the traces of your integration tests
$ perf-sentinel capture -o traces.json -- mvn verify
# 2. the gate: exit code 1 when a threshold is crossed
$ perf-sentinel analyze --input traces.json --ci
# 3. the findings in Code scanning (SARIF)
$ perf-sentinel analyze --input traces.json --format sarif > findings.sarif
GitHub Actions, GitLab CI and Jenkins templates →
$ cargo install perf-sentinel --locked
$ perf-sentinel demo # terminal report
$ perf-sentinel demo --tui # interactive TUI
$ perf-sentinel demo --html demo.html # HTML dashboard
Prebuilt binaries, Docker image and Helm chart in the guide →
Find it useful? A star helps others discover it.Perf Sentinel43Perf Sentinel Hub1
Institut du Numérique ResponsableInstitut du Numérique Responsable
// governance

Stewarded by the Institut du Numérique Responsable

Started as a personal project, Perf Sentinel has joined the INR, a French non-profit that grew out of the Club Green IT. Its creator, Robin Trassard, still leads it within the institute. Robin is also a full-stack developer at Onepoint, back-end leaning and specialized in performance and eco-design. The code stays under AGPL-3.0 and is developed in the open on the INR GitHub.

{{ skipLink }}
Perf SentinelPerf Sentinel
GitHub{{ psStarsN }}
{{ personaPrompt }} {{ personaHint }}
{{ spotTitle }}{{ spotSkip }}
{{ tipText }}
{{ dLead }}
{{ dHint }}
{{ eyebrowHero }}{{ eyebrowHeroGreen }}

{{ heroTitle }}

{{ heroSub }}

{{ inrBy }}
{{ inrArt }}{{ inrName }}
CRITN+1 HTTPGET /api/cart/enrich{{ dfCalls }} {{ dfLineA }}inventory/enrich.py:88{{ dfLineB }}
{{ dfBarsA }}GET catalog-svc/api/products/{id}{{ dfBarsB }}
{{ dfWhatT }}
{{ dfWhat }}
{{ dfCostT }}
{{ dfCost }}
{{ dfFixT }}
inventory/enrich.py:88
{{ dfFixA }}?ids=…{{ dfFixB }}
{{ dfTrace }} →
{{ embedLead }}
{{ embedOpen }}{{ embedOpenMobile }} ↗
{{ embedCaption }}
{{ embedCaptionSyn }}
{{ proofAvT }}{{ proofEq }}
{{ proofAvS }}
{{ proofFoot }}
{{ proofCalls }}
  • {{ c.t }}
{{ whyEyebrow }}

{{ whyT1 }}{{ whyTName }}{{ whyT2 }}

{{ whyP1 }}

{{ whyP2 }}

  1. {{ l.n }}{{ l.tag }}
    {{ l.title }}
    {{ l.sub }}

{{ lgcScope }}

{{ whyP3 }}

{{ whyP4 }}

{{ smpAlt }}

{{ smpT }}

{{ smpP }}

  • {{ f.t }}

{{ prereq1Label }} {{ prereq1Text }}

{{ prereq2Label }} {{ prereq2Text }}

{{ prereqNotLabel }} {{ prereqNotText }} {{ prereqNotLink }}.

{{ prereq3Label }} {{ prereq3Text }}

{{ prereqLink }}

{{ shrEyebrow }}

{{ shrT1 }}{{ shrTW }}

{{ shrIntro }}

{{ shrRecapHead }}{{ shrPeriod }}
{{ shrFixFirst }}
  1. {{ r.i }}
    {{ r.s }}
    {{ r.where }}
    {{ r.n }}{{ shrUnit }}{{ r.pill }}
{{ shrRecapCap }}
{{ shrBridge }}
{{ shrAlt }}
{{ shrCardCap }}{{ shrCo2 }}

{{ shrNeverT }}

  • {{ n.t }}
{{ detEyebrow }}

{{ detT1 }}{{ detWAnti }}{{ detT2 }}

{{ detIntro }}

{{ detMatrixLead }}

{{ c }}
{{ r.name }}
{{ r.rule }}
{{ r.ess }}
{{ r.sql }}
{{ r.http }}
{{ r.msg }}
{{ detExTitle }}{{ detExSub }}
{{ detExNeeded }}{{ detExAvoidable }}
{{ detExBefore }}
GET /api/cart/enrich
CartService::enrich
GET …/products/1
GET …/products/2
GET …/products/3
GET …/products/4
GET …/products/5
GET …/products/6
GET …/products/7
GET …/products/8
GET …/products/9
GET …/products/10
GET …/products/11
GET …/products/12
{{ detExBeforeSum }}{{ detExBeforeNote }}
{{ detExAfter }}
GET /api/cart/enrich
CartService::enrich
GET …/products?ids=1,…,12
CRITN+1 HTTPGET /api/cart/enrich
{{ detExFix }}
{{ detExAfterSum }}{{ detExAfterNote }}

{{ detStructLead }}

{{ p.labels.0 }} {{ p.labels.1 }} ABC {{ p.labels.0 }} {{ p.labels.1 }}{{ p.labels.2 }} {{ p.labels.0 }} {{ p.labels.1 }} {{ p.labels.0 }} ABC {{ p.labels.1 }} ABC {{ p.labels.2 }}

{{ p.name }}

{{ p.badge }}
{{ p.trigger }}{{ p.ess }}

{{ detFoot }}

{{ detFootEss }}

{{ stackEyebrow }}

{{ stackTitle }}

{{ stackIntro }}

{{ stackLangs }}
{{ stackFws }}{{ stackOrm }}
{{ stackLangs }}
{{ stackFws }}{{ stackOrm }}
{{ stackLink }} →
{{ modEyebrow }}

{{ modTitle }}

{{ modSrc }}
{{ s }}
{{ l.tag }}
{{ l.title }}
{{ l.sub }}
{{ o }}{{ l.hl }}
{{ d.t }}
{{ d.s }}

{{ ccTitle }}

{{ ccLead }}

{{ ccAvailPre }} Claude Code.

  1. {{ r.tag }}{{ r.cmd }}

    {{ r.text }}

# {{ ccTermCmt }}
> /plugin marketplace add Institut-du-Numerique-Responsable/perf-sentinel-claude
> /plugin install perf-sentinel@perf-sentinel
{{ ccMore }} ↗

{{ ccNote }}

{{ perfEyebrow }}

{{ perfT1 }}{{ perfWRust }}{{ perfT2 }}

{{ perfBadge }}

{{ perfIntro }}

{{ s.value }}
{{ s.label }}
{{ perfMore }} →
{{ hubEyebrow }}

{{ hubTitleB1 }}{{ hubWCs }}{{ hubTitleB2 }}

.NET{{ hubBadge }}

{{ hubLeadA }}/api/findings{{ hubLeadB }}

{{ hubLeadEss }}

perf-sentinel · daemon 1
perf-sentinel · daemon 2
perf-sentinel · daemon 3
{{ hubDmnNote }}
{{ hubPush }}
{{ hubPull }}
Perf Sentinel Hub
{{ hubKeepA }}{{ hubKeepB }}{{ hubKeepC }}
{{ c }}
{{ hubBrowser }}{{ hubLauncher }}
{{ hubPick }}
{{ hubRun }}
{{ s.value }}
{{ s.label }}
{{ s.ess }}
{{ rvwEyebrow }}

{{ rvwT1 }}{{ rvwTW }}

{{ rvwIntro }}

{{ rvwHead }}{{ rvwPeriod }}
{{ rvwSub }}{{ rvwRank }}
  1. 1
    N+1 SQL{{ rvwR1Label }}shopGET /cart/{id}

    Use WHERE ... IN (?) to batch 41 queries into one

    {{ rvwR1N }}{{ rvwUnit }}{{ rvwR1Pill }}
    {{ rvwHow }}
    SELECT * FROM cart_item WHERE cart_id = ?
    {{ rvwFix }}java_jpa

    Use JOIN FETCH on the relationship or annotate the repository method with @EntityGraph to load associations in a single query.

    {{ rvwWhere }}
    CartItemRepository.findByCartId
    shop/src/main/java/acme/cart/CartItemRepository.java:31
    {{ rvwDet }}
    {{ rvwDetN }}
    {{ rvwConf }}
    daemon_production
    signature
    n_plus_one_sql:shop:GET__cart_{id}:09908701485122dcb9d5d84b7c653b7c
  2. {{ r.i }}
    {{ r.chip }}{{ r.label }}{{ r.svc }}{{ r.ep }}

    {{ r.sug }}

    {{ r.n }}{{ rvwUnit }}{{ r.pill }}
{{ carbonEyebrow }}

{{ carbonT1 }}{{ carbonTW }}{{ carbonT2a }}
{{ carbonT2b }}{{ carbonTW2 }}{{ carbonT3 }}

{{ carbonIntro }}

{{ carbonChartTitle }}
5 %4 %3 %2 %1 %0 %
{{ carbonAnnBasse }}
{{ carbonAnnHaute }} {{ carbonAnnHauteSubPre }}{{ carbonAnnHauteQ }})
?
{{ carbonBarBasse }}
{{ carbonBarHaute }}
{{ carbonLegMeasured }}
{{ carbonLegUnmeasured }}
{{ carbonChartSrc }}ITU 2025, IEA 2025, Freitag et al. 2021
{{ carbonNarrTitle }}

{{ carbonNarrText }}

{{ carbonStatNum }}
{{ carbonStatText }}
{{ carbonCmpTitle }}

{{ carbonCmpSub }}

{{ carbonTdEyebrow }}
{{ carbonTdTitle }}
•{{ pt.t }}
{{ carbonResultLabel }}
{{ carbonTdResultA }}{{ carbonTdResultB }}{{ carbonTdResultC }}{{ carbonTdResultD }}.
{{ carbonBuEyebrow }}
{{ carbonBuTitle }}
✓{{ pt.t }}
{{ carbonResultLabel }}
{{ carbonBuResultA }}{{ carbonBuResultB }}{{ carbonBuResultC }}{{ carbonBuResultD }}.
{{ goEyebrow }}

{{ goT1 }}{{ goWCost }},
{{ goT2 }}{{ goWEnergy }}{{ goT3 }}{{ goWCarbon }}

{{ goBodyA }}co2.total{{ goBodyB1 }}Software Carbon Intensity v1.0{{ goBodyB2 }}ISO/IEC 21031:2024{{ goBodyB3 }}

{{ goBodyA }}co2.total{{ goEssB1 }}Software Carbon Intensity v1.0{{ goEssB2 }}ISO/IEC 21031:2024{{ goEssB3 }}

{{ goEqTotal }}
{{ goEqET }}
{{ goEqES }}
{{ goEqIT }}
{{ goEqIS }}
{{ goEqMT }}
{{ goEqMS }}
{{ goEqBounds }}
{{ goEqAvLabel }}{{ goEqAvText }}

{{ g.title }}

{{ g.body }}

{{ goNoteA }}{{ goNoteLink }}{{ goNoteLink }}{{ goNoteB }}

{{ goEssNoteA }}{{ goNoteLink }}{{ goEssNoteB }}

{{ mesEyebrow }}

{{ mesT1 }}{{ mesTWord }},
{{ mesT2 }}

{{ mesIntro }}

{{ mesE }}
{{ mesSoft }}
{{ mesSoftNote }}
{{ mesBadge }}
{{ mesAlumet }}
{{ mesPerCont }}
{{ mesScaph }}
{{ mesPerProc }}
{{ mesKepler }}
{{ mesPerPod }}
{{ mesWall }}
{{ mesWallNote }}
{{ mesRedfish }}
{{ mesRedfishEss }}
{{ mesWallChip }}
{{ mesLive }}

{{ mesLiveIntro }}

{{ mesOpsTitle }}{{ mesOpsFree }}
{{ mesOpsDesc }}
FR
RTE
éCO2mix
GB
NESO
Carbon Intensity API
FI
Fingrid
Open Data
DK
Energinet
Energi Data Service
ES
REE
e·sios
AU
Open Electricity
NEM · WEM
HU
MAVIR
export XLSX
NZ
em6
Transpower
{{ mesOpsOpen }}{{ mesOpsTerms }}
{{ mesEmaps }}
{{ mesKey }}{{ mesPaid }}

{{ mesLiveNote }}

{{ mesCaveat }}

{{ mesMore }} →
{{ cmpEyebrow }}

{{ cmpT1 }}{{ cmpWCarbon }}

{{ cmpHCap }}
{{ cmpHApm }}
Perf Sentinel
{{ c.cap }}
{{ c.apm }}
{{ c.ps }}

{{ cmpFoot }}

{{ cmpFootEss }}

{{ cpNotTitle }}

✗{{ n.lead }} {{ n.body }}{{ n.ess }} {{ n.refText }}.
{{ pubEyebrow }}

{{ pubT1 }}{{ pubTWord }}{{ pubT2 }}

{{ pubIntroA }}perf-sentinel disclose{{ pubIntroB }}disclose-pdf{{ pubIntroC }}

{{ smpAlt }}

{{ smpP }}

  • {{ f.t }}

{{ pubVerT }}

{{ pubVerText }}

{{ pubVerEss }}

$ curl -fsSLO https://perf-sentinel.dev/exemple/disclosure/report.pdf
$ perf-sentinel verify-hash --report report.pdf \
$ perf-sentinel verify-hash --report report.pdf
--expected-identity https://github.com/Institut-du-Numerique-Responsable/perf-sentinel/.github/workflows/sample-disclosure.yml@refs/heads/main…/sample-disclosure.yml@refs/heads/main \
--expected-issuer https://token.actions.githubusercontent.com
Overall: TRUSTED
{{ licEyebrow }}

{{ licTitleA }}{{ licTitleB }}

open source

{{ licIntro }}

✓
{{ licC1Title }}

{{ licC1Body }}

✓
{{ licC2Title }}

{{ licC2Body }}

{{ licDisclaimer }}

{{ licDisclaimerEss }}

{{ secEyebrow }}

{{ secTitle }}

{{ secIntro }}

{{ s.tag }}

{{ s.title }}

{{ s.desc }}

{{ s.ess }}

{{ secMore }} →

{{ ctaTitle }}

{{ ctaText }}

# {{ ciCmt1 }}
$ {{ ciCmd1View }}
# {{ ciCmt2 }}
$ {{ ciCmd2View }}
# {{ ciCmt3 }}
$ {{ ciCmd3View }}
{{ ctaCiLink }} →
$ {{ installView }}
$ perf-sentinel demo # {{ demoCmt1 }}
$ perf-sentinel demo --tui # {{ demoCmt2 }}
$ perf-sentinel demo --html demo.html # {{ demoCmt3 }}
{{ ctaGuide }} →
Institut du Numérique ResponsableInstitut du Numérique Responsable
{{ govEyebrow }}

{{ govTitleA }}{{ govTitleB }}

{{ govBodyA }}Robin Trassard{{ govBodyB }}

{{ dotNav }}