{
  "leansignal_demand_export": "1.0",
  "exported_at": "2026-07-17T00:00:00Z",
  "source_tenant": "leansignal-catalog",
  "catalog": {
    "slug": "nodejs-otel-demand-extended",
    "integration": "nodejs",
    "variant": "extended",
    "title": "Node.js — Extended",
    "category": "SDK",
    "dashboards": 1,
    "panels": 14,
    "alerts": 10,
    "docs_url": "https://docs.leansignal.io/integrations/nodejs/"
  },
  "demand": {
    "ref": "demand",
    "name": "Node.js — Extended (OpenTelemetry)",
    "description": "Deep runtime visibility: p99 and per-route HTTP, per-space V8 heap, GC rate by type, and heap limit, plus the full alert set including sustained heap growth (leak signal).",
    "dashboards": [
      {
        "ref": "dash-nodejs",
        "name": "Node.js — Extended",
        "description": "Node.js/V8 runtime metrics (event-loop utilization & delay, V8 heap, GC pauses) plus HTTP server request metrics (extended variant).",
        "data": {
          "display": {
            "name": "Node.js — Extended"
          },
          "panels": {
            "http_request_rate": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "HTTP request rate",
                  "description": "Inbound request throughput per instance."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "requests/sec"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (instance) (rate(http_server_request_duration_seconds_count{instance=~\"$instance\"}[5m]))",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "http_error_rate": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "HTTP 5xx error rate",
                  "description": "Share of requests answered 5xx."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "percent-decimal"
                      },
                      "min": 0,
                      "max": 1
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (instance) (rate(http_server_request_duration_seconds_count{instance=~\"$instance\",http_response_status_code=~\"5..\"}[5m])) / sum by (instance) (rate(http_server_request_duration_seconds_count{instance=~\"$instance\"}[5m]))",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "http_latency_p95": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "HTTP request duration p95",
                  "description": "95th-percentile request latency per instance."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "seconds"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "histogram_quantile(0.95, sum by (instance, le) (rate(http_server_request_duration_seconds_bucket{instance=~\"$instance\"}[5m])))",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "http_latency_p99": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "HTTP request duration p99",
                  "description": "Tail latency — compare with p95 to see how bad the worst requests get."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "seconds"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "histogram_quantile(0.99, sum by (instance, le) (rate(http_server_request_duration_seconds_bucket{instance=~\"$instance\"}[5m])))",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "http_request_rate_by_route": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "HTTP request rate by route",
                  "description": "Service-level traffic per route, summed across the selected instances."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "requests/sec"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (http_route) (rate(http_server_request_duration_seconds_count{instance=~\"$instance\"}[5m]))",
                          "seriesNameFormat": "{{http_route}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "eventloop_utilization": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "Event-loop utilization",
                  "description": "Share of time the loop is busy — Node’s single most important saturation signal."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "percent-decimal"
                      },
                      "min": 0,
                      "max": 1
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "max by (instance) (nodejs_eventloop_utilization_ratio{instance=~\"$instance\"})",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "eventloop_delay_p99": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "Event-loop delay p99",
                  "description": "How late timers fire — blocking work on the loop shows up here."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "seconds"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "max by (instance) (nodejs_eventloop_delay_p99_seconds{instance=~\"$instance\"})",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "eventloop_delay_p50": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "Event-loop delay p50",
                  "description": "Median loop delay — compare with p99 to separate spikes from constant pressure."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "seconds"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "max by (instance) (nodejs_eventloop_delay_p50_seconds{instance=~\"$instance\"})",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "heap_used": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "V8 heap used",
                  "description": "Absolute heap in use — the sawtooth is healthy GC behavior."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "bytes"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (instance) (v8js_memory_heap_used_bytes{instance=~\"$instance\"})",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "heap_utilization": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "V8 heap utilization",
                  "description": "Heap used as a share of the pre-allocated heap."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "percent-decimal"
                      },
                      "min": 0,
                      "max": 1
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (instance) (v8js_memory_heap_used_bytes{instance=~\"$instance\"}) / sum by (instance) (v8js_memory_heap_limit_bytes{instance=~\"$instance\"})",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "heap_used_by_space": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "V8 heap used by space",
                  "description": "new/old/code/large-object spaces — old-space growth is the leak signal."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "bytes"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (instance, v8js_heap_space_name) (v8js_memory_heap_used_bytes{instance=~\"$instance\"})",
                          "seriesNameFormat": "{{instance}} · {{v8js_heap_space_name}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "heap_limit": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "V8 heap limit (pre-allocated)",
                  "description": "Summed pre-allocated heap-space size — the denominator of the utilization panel, not the --max-old-space-size ceiling."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "bytes"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (instance) (v8js_memory_heap_limit_bytes{instance=~\"$instance\"})",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "gc_pause_p95": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "GC pause duration p95",
                  "description": "Collection pause latency — pauses block the event loop."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "seconds"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "histogram_quantile(0.95, sum by (instance, le) (rate(v8js_gc_duration_seconds_bucket{instance=~\"$instance\"}[5m])))",
                          "seriesNameFormat": "{{instance}}"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "gc_rate_by_type": {
              "kind": "Panel",
              "spec": {
                "display": {
                  "name": "GC collections by type",
                  "description": "Major vs minor vs incremental collections — frequent majors mean heap pressure."
                },
                "plugin": {
                  "kind": "TimeSeriesChart",
                  "spec": {
                    "legend": {
                      "position": "bottom",
                      "mode": "table",
                      "values": [
                        "last-number",
                        "mean",
                        "max"
                      ]
                    },
                    "yAxis": {
                      "format": {
                        "unit": "ops/sec"
                      },
                      "min": 0
                    }
                  }
                },
                "queries": [
                  {
                    "kind": "TimeSeriesQuery",
                    "spec": {
                      "plugin": {
                        "kind": "PrometheusTimeSeriesQuery",
                        "spec": {
                          "query": "sum by (instance, v8js_gc_type) (rate(v8js_gc_duration_seconds_count{instance=~\"$instance\"}[5m]))",
                          "seriesNameFormat": "{{instance}} · {{v8js_gc_type}}"
                        }
                      }
                    }
                  }
                ]
              }
            }
          },
          "layouts": [
            {
              "kind": "Grid",
              "spec": {
                "display": {
                  "title": "HTTP",
                  "collapse": {
                    "open": true
                  }
                },
                "items": [
                  {
                    "x": 0,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/http_request_rate"
                    }
                  },
                  {
                    "x": 12,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/http_error_rate"
                    }
                  },
                  {
                    "x": 0,
                    "y": 8,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/http_latency_p95"
                    }
                  },
                  {
                    "x": 12,
                    "y": 8,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/http_latency_p99"
                    }
                  },
                  {
                    "x": 0,
                    "y": 16,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/http_request_rate_by_route"
                    }
                  }
                ]
              }
            },
            {
              "kind": "Grid",
              "spec": {
                "display": {
                  "title": "Event Loop",
                  "collapse": {
                    "open": true
                  }
                },
                "items": [
                  {
                    "x": 0,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/eventloop_utilization"
                    }
                  },
                  {
                    "x": 12,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/eventloop_delay_p99"
                    }
                  },
                  {
                    "x": 0,
                    "y": 8,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/eventloop_delay_p50"
                    }
                  }
                ]
              }
            },
            {
              "kind": "Grid",
              "spec": {
                "display": {
                  "title": "Memory",
                  "collapse": {
                    "open": true
                  }
                },
                "items": [
                  {
                    "x": 0,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/heap_used"
                    }
                  },
                  {
                    "x": 12,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/heap_utilization"
                    }
                  },
                  {
                    "x": 0,
                    "y": 8,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/heap_used_by_space"
                    }
                  },
                  {
                    "x": 12,
                    "y": 8,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/heap_limit"
                    }
                  }
                ]
              }
            },
            {
              "kind": "Grid",
              "spec": {
                "display": {
                  "title": "GC",
                  "collapse": {
                    "open": true
                  }
                },
                "items": [
                  {
                    "x": 0,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/gc_pause_p95"
                    }
                  },
                  {
                    "x": 12,
                    "y": 0,
                    "width": 12,
                    "height": 8,
                    "content": {
                      "$ref": "#/spec/panels/gc_rate_by_type"
                    }
                  }
                ]
              }
            }
          ],
          "variables": [
            {
              "kind": "ListVariable",
              "spec": {
                "name": "instance",
                "display": {
                  "name": "Instance"
                },
                "allowAllValue": true,
                "allowMultiple": true,
                "customAllValue": ".*",
                "defaultValue": ".*",
                "plugin": {
                  "kind": "PrometheusLabelValuesVariable",
                  "spec": {
                    "labelName": "instance"
                  }
                }
              }
            }
          ],
          "duration": "1h",
          "refreshInterval": "30s",
          "datasources": {}
        }
      }
    ],
    "alert_rules": [
      {
        "ref": "alert-high-http-error-rate",
        "name": "High HTTP 5xx error rate",
        "description": null,
        "query": "sum by (instance) (rate(http_server_request_duration_seconds_count{http_response_status_code=~\"5..\"}[5m])) / sum by (instance) (rate(http_server_request_duration_seconds_count[5m]))",
        "condition_op": "gt",
        "threshold": 0.05,
        "interval": "1m",
        "for": "5m",
        "severity": "critical",
        "message": "{{labels.instance}} is serving {{value | percent:1}} 5xx responses.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-high-http-latency-p95",
        "name": "High HTTP p95 latency",
        "description": null,
        "query": "histogram_quantile(0.95, sum by (instance, le) (rate(http_server_request_duration_seconds_bucket[5m])))",
        "condition_op": "gt",
        "threshold": 1,
        "interval": "1m",
        "for": "5m",
        "severity": "warning",
        "message": "{{labels.instance}} p95 request latency is {{value}}s.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-high-eventloop-utilization",
        "name": "Event-loop saturated",
        "description": null,
        "query": "max by (instance) (nodejs_eventloop_utilization_ratio)",
        "condition_op": "gt",
        "threshold": 0.9,
        "interval": "1m",
        "for": "5m",
        "severity": "critical",
        "message": "{{labels.instance}} event-loop utilization is {{value | percent:1}} — the event loop is starved.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-high-eventloop-delay",
        "name": "High event-loop delay",
        "description": null,
        "query": "max by (instance) (nodejs_eventloop_delay_p99_seconds)",
        "condition_op": "gt",
        "threshold": 0.1,
        "interval": "1m",
        "for": "5m",
        "severity": "warning",
        "message": "{{labels.instance}} p99 event-loop delay is {{value}}s — blocking work on the loop.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-heap-near-limit",
        "name": "V8 heap near limit",
        "description": null,
        "query": "sum by (instance) (min_over_time(v8js_memory_heap_used_bytes[10m])) / sum by (instance) (v8js_memory_heap_limit_bytes)",
        "condition_op": "gt",
        "threshold": 0.9,
        "interval": "1m",
        "for": "5m",
        "severity": "critical",
        "message": "{{labels.instance}} V8 heap stays above {{value | percent:1}} of pre-allocated size even after GC — risk of OOM/GC thrash.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-gc-pause-high",
        "name": "High GC pause duration",
        "description": null,
        "query": "histogram_quantile(0.95, sum by (instance, le) (rate(v8js_gc_duration_seconds_bucket[5m])))",
        "condition_op": "gt",
        "threshold": 0.1,
        "interval": "1m",
        "for": "10m",
        "severity": "warning",
        "message": "{{labels.instance}} p95 GC pause is {{value}}s — GC pressure.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-critical-http-latency-p99",
        "name": "Critical HTTP p99 latency",
        "description": null,
        "query": "histogram_quantile(0.99, sum by (instance, le) (rate(http_server_request_duration_seconds_bucket[5m])))",
        "condition_op": "gt",
        "threshold": 3,
        "interval": "1m",
        "for": "5m",
        "severity": "critical",
        "message": "{{labels.instance}} p99 request latency is {{value}}s.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-elevated-http-4xx",
        "name": "Elevated HTTP 4xx rate",
        "description": null,
        "query": "sum by (instance) (rate(http_server_request_duration_seconds_count{http_response_status_code=~\"4..\"}[5m])) / sum by (instance) (rate(http_server_request_duration_seconds_count[5m]))",
        "condition_op": "gt",
        "threshold": 0.3,
        "interval": "1m",
        "for": "10m",
        "severity": "warning",
        "message": "{{labels.instance}} 4xx ratio is {{value | percent:1}}.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-eventloop-utilization-warning",
        "name": "Elevated event-loop utilization",
        "description": null,
        "query": "max by (instance) (nodejs_eventloop_utilization_ratio)",
        "condition_op": "gt",
        "threshold": 0.7,
        "interval": "1m",
        "for": "10m",
        "severity": "warning",
        "message": "{{labels.instance}} event-loop utilization sustained at {{value | percent:1}}.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      },
      {
        "ref": "alert-heap-growth",
        "name": "Sustained heap growth",
        "description": null,
        "query": "sum by (instance) (v8js_memory_heap_used_bytes) - sum by (instance) (v8js_memory_heap_used_bytes offset 30m)",
        "condition_op": "gt",
        "threshold": 268435456,
        "interval": "1m",
        "for": "15m",
        "severity": "warning",
        "message": "{{labels.instance}} V8 heap grew by {{value | bytes}} over 30m — possible memory leak.",
        "notify_on_resolve": true,
        "paused": false,
        "channels": []
      }
    ]
  }
}
