Elastic APM’s transaction breakdown metrics reveal how much time is spent in different layers of your application, pinpointing the slowest components and helping you optimize performance.

Let’s see this in action with a hypothetical e-commerce checkout process.

Imagine a user initiates a checkout. This is one transaction. Elastic APM captures this transaction and breaks it down into several spans:

{
  "transaction.id": "a1b2c3d4e5f6",
  "transaction.name": "POST /checkout",
  "transaction.type": "request",
  "duration.us": 1500000, // 1.5 seconds total
  "span_count": {
    "total": 10,
    "dropped": 0
  },
  "breakdown": {
    "service": {
      "database": {
        "count": 3,
        "duration.us": 500000 // 0.5 seconds spent in DB calls
      },
      "external": {
        "count": 2,
        "duration.us": 300000 // 0.3 seconds spent in external APIs
      },
      "app": {
        "count": 5,
        "duration.us": 700000 // 0.7 seconds spent in application code
      }
    }
  }
}

In this snippet, the transaction.id a1b2c3d4e5f6 for the /checkout request took 1.5 seconds. The breakdown object shows where that time went: 0.5 seconds in database calls, 0.3 seconds in external API calls, and 0.7 seconds in the application’s own code. This immediately tells us the database is a significant bottleneck.

The core problem Elastic APM’s transaction breakdown solves is the "where is the time going?" question for your application requests. Without it, you’re left guessing whether a slow request is due to network latency, database queries, external service calls, or your own inefficient code. It provides a hierarchical view of execution time, allowing you to drill down from the top-level transaction into specific spans representing different operations.

Internally, APM agents instrument your application code. When a transaction starts, the agent begins timing. As your code executes functions, makes database queries, or calls external HTTP endpoints, the agent creates child spans for these operations, recording their start time, end time, and type. These spans are then associated with the parent transaction. The breakdown metrics are aggregated from these spans.

The key levers you control are the APM agent’s configuration and how you instrument your code. For example, you can configure sampling rates to control how many transactions are reported, which impacts the granularity of your breakdown data versus the overhead. More importantly, custom instrumentation allows you to define specific spans for critical business logic that might not be automatically captured, giving you even finer-grained insights into your application’s performance.

The breakdown.service.app duration isn’t just a sum of all spans within your application code; it represents the time spent in spans that are not categorized as database, external, or other specific types. This means if you have a custom span for a complex calculation within your app, and it’s not explicitly marked as db or external, its duration contributes to app time. This can sometimes obscure the true cost of specific internal operations if they aren’t further broken down into their own meaningful spans.

The next concept you’ll likely explore is distributed tracing, which connects transactions across multiple services.

Want structured learning?

Take the full Elastic-apm course →