Skip to main content

Documentation Index

Fetch the complete documentation index at: https://tyk.io/docs/llms.txt

Use this file to discover all available pages before exploring further.

Availability

ComponentVersionEdition
Tyk GatewayAvailable since v5.13.0Community & Enterprise

Custom Metrics

By default, Tyk Gateway exports standard RED metrics with a fixed set of dimensions. Custom metrics let you define additional instruments with dimensions drawn from request headers, session data, JWT claims, and other context, enabling use cases such as:
  • Multi-tenant billing: Count requests per customer ID from a header or JWT claim
  • Tier-based SLOs: Track latency separately for premium vs. standard API tiers
  • Business KPIs: Measure domain-specific signals (e.g., successful transactions per payment provider)

The api_metrics Array

Custom metrics are defined in the api_metrics array inside opentelemetry.metrics:
{
  "opentelemetry": {
    "metrics": {
      "enabled": true,
      "api_metrics": [
        { ... }
      ]
    }
  }
}
The behavior of this field depends on its value:
ValueBehavior
Field omitted or nullDefault RED metrics are exported automatically.
Empty array []API-level metrics are disabled entirely; no request metrics are exported.
Populated arrayOnly the instruments you define are exported. Default RED metrics are not exported unless you explicitly define them.
Preserving default RED metricsWhen you populate api_metrics, the built-in RED instruments are no longer exported automatically. Use the block below as a starting point, it re-creates all four default instruments, then append your custom instruments after them.
{
  "opentelemetry": {
    "metrics": {
      "enabled": true,
      "api_metrics": [
        {
          "name": "http.server.request.duration",
          "type": "histogram",
          "description": "End-to-end request latency",
          "histogram_source": "total",
          "dimensions": [
            { "source": "metadata", "key": "method",        "label": "http.request.method" },
            { "source": "metadata", "key": "response_code", "label": "http.response.status_code" },
            { "source": "metadata", "key": "api_id",        "label": "tyk.api.id" },
            { "source": "metadata", "key": "response_flag", "label": "tyk.response_flag" }
          ]
        },
        {
          "name": "tyk.gateway.request.duration",
          "type": "histogram",
          "description": "Gateway processing time",
          "histogram_source": "gateway",
          "dimensions": [
            { "source": "metadata", "key": "method",        "label": "http.request.method" },
            { "source": "metadata", "key": "api_id",        "label": "tyk.api.id" },
            { "source": "metadata", "key": "response_flag", "label": "tyk.response_flag" }
          ]
        },
        {
          "name": "tyk.upstream.request.duration",
          "type": "histogram",
          "description": "Upstream response time",
          "histogram_source": "upstream",
          "dimensions": [
            { "source": "metadata", "key": "method",        "label": "http.request.method" },
            { "source": "metadata", "key": "api_id",        "label": "tyk.api.id" },
            { "source": "metadata", "key": "response_flag", "label": "tyk.response_flag" }
          ]
        },
        {
          "name": "tyk.api.requests.total",
          "type": "counter",
          "description": "Request count with identity dimensions",
          "dimensions": [
            { "source": "metadata", "key": "method",        "label": "http.request.method" },
            { "source": "metadata", "key": "response_code", "label": "http.response.status_code" },
            { "source": "metadata", "key": "api_id",        "label": "tyk.api.id" }
          ]
        }
      ]
    }
  }
}

Instrument Types

Each entry in api_metrics defines one instrument:
TypeDescription
counterA monotonically increasing count. Use for request counts, error counts, etc.
histogramA distribution of values. Use for latency measurements.
Histograms require a histogram_source field that selects which latency to measure:
histogram_sourceMeasures
totalEnd-to-end request latency (client to Gateway to upstream)
gatewayGateway processing time only (excludes upstream response time)
upstreamUpstream service response time only

Dimension Sources

Dimensions let you slice your metrics by any signal available at request time. Tyk can source dimension values from six places; the sections below describe common use cases and which source and key to use for each.
SourceWhat It ProvidesExample Keys
metadataRequest metadata always in scopemethod, response_code, api_id, api_name, org_id, response_flag, ip_address, api_version, host, scheme, listen_path, endpoint. MCP APIs also expose mcp_method, mcp_primitive_type, mcp_primitive_name, mcp_error_code, see MCP dimensions.
sessionAuthenticated session fieldsapi_key, oauth_id, alias, portal_app, portal_org
headerAny HTTP request headerX-Customer-ID, X-Tenant-ID, Authorization
contextTyk context variablesjwt_claims_tier, request_id, path_parts
response_headerAny upstream response headerX-Cache-Status, X-Backend-Version
config_dataAPI definition metadata from the config_data mapAny key set on the API definition

Response status

Two metadata keys capture response status, and they answer different questions:
KeySourceWhat it captures
response_codemetadataThe numeric HTTP status code returned to the client (200, 429, 502, etc.). Always populated. Bounded cardinality (~100 values).
response_flagmetadataA 3-letter error classification code set by the gateway, e.g. URS (upstream returned 5XX), AKI (API key invalid), CBO (circuit breaker open). Falls back to the HTTP status code string (e.g. "200") when no error classification applies. See the full list of response flags.
Use response_code to break down traffic by HTTP status. Use response_flag to understand Gateway-level error causes. The status_codes filter in the filters block decides whether a request is recorded at all. The response_code dimension attaches the actual code as a label on the recorded data points. A common pattern is to combine both: filter to error responses, then break them down by exact code:
{
  "name": "tyk.api.errors.by_status",
  "type": "counter",
  "dimensions": [
    { "source": "metadata", "key": "response_code", "label": "http_status_code" },
    { "source": "metadata", "key": "api_id",        "label": "api_id" }
  ],
  "filters": { "status_codes": ["4xx", "5xx"] }
}

Request path

Four options are available, at different cardinality levels:
SourceKeyCardinalityNotes
API listen pathmetadatalisten_pathBounded (one value per API)The configured listen path (e.g. /api/v1/). Safe to use in any metric.
Endpoint templatemetadataendpointBounded (one per track endpoint)The matched path template (e.g. /user/{id}). Requires track_endpoints configured on the API. Empty string for unmatched requests.
Raw request pathcontextpath⚠️ Potentially unboundedThe URL path as requested by the client (e.g. /api/v1/users/12345). Avoid unless paths have known low cardinality.
Path segmentscontextpath_parts⚠️ Potentially unboundedThe path split by / into a list of segments (e.g. /api/v1/users/123["api", "v1", "users", "123"]). Access a specific segment with {{ index ._tyk_context.path_parts N }}. Carries the same cardinality risk as path if any segment varies per request.
Prefer listen_path or endpoint (with track_endpoints) over raw path or path_parts in most cases.

Client and auth identity

Several sources expose client identity, with different cardinality trade-offs:
  • Session fields (session source): alias (the human-readable key alias), portal_app (Developer Portal app ID), and portal_org (Developer Portal org ID) are typically bounded and safe to use. api_key and oauth_id are ⚠️ high cardinality (one value per key/client); only use these with cardinality control enabled.
  • JWT claims (context source): any claim is available as jwt_claims_<name> (e.g. jwt_claims_tier, jwt_claims_tenant_id). See Request context variables for setup requirements and cardinality notes.
  • Request headers (header source): use when client identity is passed as a header (e.g. X-Tenant-ID). Cardinality depends on what the header contains.

Custom API metadata

If you want to attach static, API-level metadata (such as team ownership, service tier, cost centre, or criticality) to your metrics without touching request headers or tokens, use the config_data source. The config_data field in the API definition is a free-form key-value map you can populate per API:
{
  "config_data": {
    "environment": "staging",
    "team": "platform",
    "criticality": "high"
  }
}
A dimension like {"source": "config_data", "key": "team"} will carry team="platform" on every metric recorded for that API; no request modification required. Fallback behaviour: If config_data_disabled is true on the API, or the key is absent, the dimension falls back to the default value on the dimension definition. If no default is set, an empty string is used. All values are treated as strings.

Request context variables

The context source reads from Tyk’s request context variables, a set of values extracted from the incoming request and enriched during middleware processing. The context source covers two kinds of variables: those populated automatically by Tyk, and those written by custom plugins.
Context variables must be enabled on the API definition (enable_context_vars: true) for the context source to work. Without this setting, all context dimensions will be empty.

Default context variables (no plugin required)

When context variables are enabled, Tyk automatically populates the following variables for every request:
KeyDescriptionCardinality
request_idA generated correlation ID for the request.⚠️ Unbounded, unique per request. Not suitable as a metric dimension.
pathThe raw request path (e.g. /api/v1/users/123).⚠️ Potentially unbounded. See Request path.
path_partsThe request path split by / into a list of segments. E.g. /api/v1/users/123["api", "v1", "users", "123"]. Access individual segments with {{ index ._tyk_context.path_parts N }}.⚠️ Potentially unbounded.
remote_addrThe connecting client IP address.⚠️ High cardinality.
jwt_claims_<name>Individual JWT claims, e.g. jwt_claims_tier, jwt_claims_tenant_id. Available when JWT auth is in use.Bounded if the claim takes a fixed set of values (e.g. subscription tier). Safe to use.
cookies_<name>Cookie values by name (hyphens replaced with underscores).Depends on cookie values.
headers_<name>Request header values by name (capitalised, hyphens replaced with underscores, e.g. headers_User_Agent).Depends on header values.
tokenThe raw inbound bearer token.⚠️ Extremely high cardinality. Do not use as a dimension.
Usually the most useful defaults for metrics are JWT claims: they let you segment traffic by tenant, subscription tier, or any other bounded claim without requiring a plugin:
{ "source": "context", "key": "jwt_claims_tier", "label": "tier", "default": "standard" }

Custom context variables (via plugin)

Go plugins and JQ request transforms can write arbitrary variables into the request context, which are then accessible as context source dimensions. This is useful for computed signals, such as enriched tenant IDs, feature flags, routing decisions, or values decoded from opaque tokens. Go plugin:
import "github.com/TykTechnologies/tyk/ctx"

func MyPlugin(w http.ResponseWriter, r *http.Request) {
    if ctxData, ok := r.Context().Value(ctx.ContextData).(map[string]interface{}); ok {
        ctxData["my_custom_var"] = "value"
    }
}
JQ transform: return a tyk_context object alongside the transformed body:
{
  "body": "<transformed-body>",
  "tyk_context": { "my_custom_var": "value" }
}
The variable is then available as a dimension:
{ "source": "context", "key": "my_custom_var", "label": "my_variable" }
Python, gRPC (coprocess), and JavaScript (JSVM) plugins cannot write to request context variables. To pass data from these plugins into metrics dimensions, use session metadata (session source, via session.meta_data) or inject a custom HTTP request header (header source) instead.

MCP dimensions

When a request is handled by an MCP API, Tyk populates four additional metadata keys derived from the JSON-RPC payload. These are available as dimensions in any custom metric instrument.
KeyDescriptionExample ValuesCardinality
mcp_methodJSON-RPC method invokedtools/call, initialize, resources/read, prompts/getBounded
mcp_primitive_typeMCP primitive categorytool, resource, promptBounded (3 values)
mcp_primitive_nameName of the specific tool, resource, or promptget_current_weather, search_docsBounded per API
mcp_error_codeJSON-RPC error code on failure; empty string on success-32001, -32002, “Bounded
These keys are only populated for MCP APIs. For non-MCP requests all four keys resolve to an empty string; use the default field on the dimension definition to set a fallback value. There is no performance overhead on non-MCP metric configurations.
Example: count tool calls by tool name:
{
  "name": "tyk.mcp.tool_calls.total",
  "type": "counter",
  "description": "MCP tool invocations by tool name and API",
  "dimensions": [
    { "source": "metadata", "key": "mcp_primitive_name", "label": "tool_name", "default": "" },
    { "source": "metadata", "key": "mcp_primitive_type", "label": "primitive_type", "default": "" },
    { "source": "metadata", "key": "api_id",             "label": "api_id" }
  ],
  "filters": { "methods": ["POST"] }
}
For a complete set of MCP monitoring use cases, see MCP Observability.

Other request metadata

Remaining metadata keys available for general request context:
KeyDescriptionCardinality
methodHTTP method (GET, POST, etc.)Bounded
api_idTyk API IDBounded
api_nameAPI display nameBounded
org_idOrganisation IDBounded
api_versionAPI version nameBounded
hostRequest hostTypically bounded
schemeURL scheme (http, https)Bounded
ip_addressClient IP address⚠️ High cardinality
Each dimension definition has four fields:
FieldRequiredDescription
sourceYesOne of the source names above.
keyYesThe specific field or header name to read from.
labelYesThe dimension name as it appears in your metrics backend.
defaultNoFallback value when the key is not present on the request.

Filters

Each instrument can restrict which requests it records using the filters block. All filter conditions use AND logic (a request must match all specified filters):
Filter FieldTypeDescription
api_idsstring arrayOnly record requests to these API IDs.
methodsstring arrayOnly record requests with these HTTP methods (e.g., ["GET", "POST"]).
status_codesstring arrayOnly record responses with these status codes. Supports exact values ("200") and class patterns ("2xx", "4xx", "5xx").

Example Configuration

The following example defines two custom instruments:
  1. A counter that tracks requests by customer ID and subscription tier
  2. A histogram that tracks latency for premium-tier requests only
{
  "opentelemetry": {
    "metrics": {
      "enabled": true,
      "api_metrics": [
        {
          "name": "tyk.requests.by_customer",
          "type": "counter",
          "description": "Request count by customer ID and subscription tier",
          "dimensions": [
            {
              "source": "header",
              "key": "X-Customer-ID",
              "label": "customer_id",
              "default": "unknown"
            },
            {
              "source": "context",
              "key": "jwt_claims_tier",
              "label": "tier",
              "default": "standard"
            },
            {
              "source": "metadata",
              "key": "api_id",
              "label": "api_id"
            }
          ],
          "filters": {
            "api_ids": ["payments-api", "orders-api"]
          }
        },
        {
          "name": "tyk.latency.premium_tier",
          "type": "histogram",
          "description": "End-to-end latency for premium tier requests",
          "histogram_source": "total",
          "histogram_buckets": [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
          "dimensions": [
            {
              "source": "context",
              "key": "jwt_claims_tier",
              "label": "tier"
            },
            {
              "source": "metadata",
              "key": "api_id",
              "label": "api_id"
            }
          ],
          "filters": {
            "methods": ["POST", "PUT", "PATCH"],
            "status_codes": ["2xx"]
          }
        }
      ]
    }
  }
}

Full Field Reference

FieldTypeRequiredDescription
namestringYesMetric instrument name. Use lowercase with dots or underscores (e.g., tyk.requests.by_customer).
typestringYes"counter" or "histogram".
descriptionstringNoHuman-readable description included in metric metadata.
dimensionsarrayYesList of dimension definitions. See Dimension Sources.
filtersobjectNoRestricts which requests are recorded. See Filters.
histogram_sourcestringHistograms only"total", "gateway", or "upstream".
histogram_bucketsfloat arrayNoCustom histogram bucket boundaries in seconds. If omitted, OTel default buckets are used.

Cardinality Considerations

Custom dimensions can significantly increase cardinality. Before adding a dimension, estimate the number of unique values it can take:
  • api_id: bounded (tens or hundreds of APIs)
  • method: bounded (fewer than 10 values)
  • customer_id from a header: potentially unbounded if unique per user
The cardinality_limit setting (default: 2,000 unique combinations per instrument) protects against unbounded cardinality. When the limit is reached, new combinations are tracked in an overflow bucket. See Cardinality Control for details.
On Tyk Cloud, custom metric configuration is not currently self-service. Contact Tyk support to request custom dimensions for your Cloud deployment.