> ## Documentation Index
> Fetch the complete documentation index at: https://sentrydocs.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Performance Monitoring

> Trace slow transactions and find performance bottlenecks

Performance Monitoring gives you end-to-end visibility into how your application behaves under real conditions. You can trace a single user request across every service it touches, measure latency percentiles, track Web Vitals, and get alerted when things slow down.

## Core concepts

<CardGroup cols={3}>
  <Card title="Transactions" icon="arrow-right-arrow-left">
    A transaction represents a single operation — an HTTP request, a background job, or a page load. It's the top-level unit Sentry measures.
  </Card>

  <Card title="Spans" icon="timeline">
    Spans are the individual steps inside a transaction — a database query, an external API call, a template render. Each span has a start time and duration.
  </Card>

  <Card title="Traces" icon="diagram-project">
    A trace connects spans across multiple services. When a frontend page load triggers a backend API call that queries a database, all three appear in the same trace.
  </Card>
</CardGroup>

## Distributed tracing

When you instrument multiple services with Sentry, a **trace** ties them all together using a propagated `trace_id`. You can follow a single user's request from the browser, through your API gateway, into your microservices, and down to the database — all in one waterfall view.

Sentry automatically propagates trace context in HTTP headers (using the W3C `traceparent` standard) when you use the SDK's HTTP instrumentation.

## Transaction performance

The **Performance** section in Sentry shows aggregated metrics for every transaction your application receives:

| Metric           | Description                                                |
| ---------------- | ---------------------------------------------------------- |
| **P50**          | Median response time — half of requests are faster         |
| **P75**          | 75th percentile — a good proxy for typical user experience |
| **P95**          | 95th percentile — captures the slowest 5% of requests      |
| **P99**          | 99th percentile — your worst-case outliers                 |
| **Throughput**   | Requests per minute                                        |
| **Failure rate** | Percentage of transactions that errored                    |

Click into any transaction to see a breakdown by span operation type (db, http, cache, etc.) and identify where time is being spent.

## Web Vitals

For browser-instrumented pages, Sentry tracks the [Core Web Vitals](https://web.dev/vitals/) defined by Google:

| Vital                              | What it measures                                              |
| ---------------------------------- | ------------------------------------------------------------- |
| **LCP** (Largest Contentful Paint) | How long until the main content is visible                    |
| **FID** (First Input Delay)        | How quickly the page responds to the first interaction        |
| **CLS** (Cumulative Layout Shift)  | How much the page layout shifts unexpectedly                  |
| **FCP** (First Contentful Paint)   | How long until any content is painted                         |
| **TTFB** (Time to First Byte)      | How long the browser waits for the first byte from the server |

Sentry scores each vital as Good, Needs Improvement, or Poor using Google's thresholds, and shows you the distribution across all page loads.

## N+1 query detection

Sentry automatically detects **N+1 query patterns** — where your code issues the same database query repeatedly in a loop instead of batching them. These show up as performance issues in the **Performance** tab, linked to the specific transaction and code location causing the problem.

## Instrumenting your code

<Tabs>
  <Tab title="Auto-instrumentation">
    Most frameworks are instrumented automatically. When you initialize the Sentry SDK, it patches common libraries (Express, Django, Flask, Rails, etc.) to create spans for HTTP requests, database queries, and more — with no additional code.

    ```javascript theme={null}
    import * as Sentry from "@sentry/node";

    Sentry.init({
      dsn: "https://your-dsn@sentry.io/project-id",
      tracesSampleRate: 1.0, // Capture 100% of transactions
    });
    ```

    ```python theme={null}
    import sentry_sdk

    sentry_sdk.init(
        dsn="https://your-dsn@sentry.io/project-id",
        traces_sample_rate=1.0,
    )
    ```
  </Tab>

  <Tab title="Manual spans">
    Use the SDK to manually create transactions and spans around any code you want to measure.

    <CodeGroup>
      ```javascript JavaScript theme={null}
      import * as Sentry from "@sentry/browser";

      // Wrap code in a span — Sentry creates the transaction automatically
      await Sentry.startSpan(
        { name: "process-order", op: "task" },
        async () => {
          // Create a child span for the database query
          await Sentry.startSpan(
            { op: "db.query", name: "SELECT * FROM orders WHERE id = ?" },
            async () => {
              await fetchOrderFromDb(orderId);
            }
          );
        }
      );
      ```

      ```python Python theme={null}
      import sentry_sdk

      with sentry_sdk.start_transaction(name="process-order", op="task"):
          with sentry_sdk.start_span(op="db.query", description="fetch order"):
              order = fetch_order_from_db(order_id)

          with sentry_sdk.start_span(op="http.client", description="notify warehouse"):
              notify_warehouse(order)
      ```
    </CodeGroup>
  </Tab>
</Tabs>

<Note>
  Set `tracesSampleRate` between `0.0` and `1.0` to control what fraction of transactions Sentry records. For high-traffic apps, start with a lower value like `0.1` (10%) to manage volume.
</Note>

## Sampling

Sentry supports **uniform sampling** (send X% of all transactions) and **dynamic sampling** (prioritize transactions with errors, specific users, or custom criteria). Configure sampling in `Sentry.init`:

```javascript theme={null}
Sentry.init({
  tracesSampleRate: 0.2, // 20% of all transactions

  // Or use a function for dynamic sampling
  tracesSampler: (samplingContext) => {
    if (samplingContext.transactionContext.name === "/health") {
      return 0; // Never sample health checks
    }
    return 0.2;
  },
});
```

## Performance dashboard

The **Performance** section in your Sentry project gives you:

* A list of all transactions, sortable by P95 latency, throughput, or failure rate
* A **transaction summary** page for any individual transaction showing latency distribution, related issues, and span breakdown
* **Web Vitals** summary for frontend projects
* **Trends** view to spot transactions that got slower or faster between releases
