skip to content

Your team keeps one near-identical Amazon CloudWatch dashboard per environment and per region, and every widget change has to be made four times. How do CloudWatch dashboard variables let you collapse those copies into one dashboard?

level: middleimportance: nice to knowfreq 30%

answer

  1. one definition, a picker on top
  2. property versus pattern
  3. dimension, region or account swap
  4. textual replace hits more than you meant
  5. selection travels in the URL

basics

~20 s

CloudWatch dashboard variables add a control at the top of a dashboard that rewrites its widgets on selection. A property variable swaps a value such as a dimension, region or account across all widgets; a pattern variable substitutes a matched string anywhere in the dashboard JSON.

solid answer

~60 s

CloudWatch dashboards support variables declared in a `variables` array in the dashboard body, each rendering as a drop-down, radio group or text input above the widgets. There are two kinds. A **property variable** targets a named widget property — a metric dimension such as `InstanceId`, or `region`, or the account — and CloudWatch substitutes the selected value into every widget that has that property. A **pattern variable** is blunter: it matches a literal string in the dashboard JSON and replaces every occurrence, which is how you parameterise things that are not a first-class property, such as a name fragment shared by log groups and resource IDs. Values can be a list you enumerate, or discovered dynamically from a metric search so the drop-down reflects what actually exists. The result is one dashboard definition to maintain instead of four, and one place to add a widget. The catch is that a variable only reaches widgets whose JSON actually contains the property or pattern, so a hand-edited widget silently ignores it.

code

json · 32 lines
json
{
  "variables": [
    {
      "type": "property",
      "property": "FunctionName",
      "inputType": "select",
      "id": "fn",
      "label": "Function",
      "defaultValue": "checkout-api",
      "values": [
        { "value": "checkout-api" },
        { "value": "payments-worker" }
      ]
    }
  ],
  "widgets": [
    {
      "type": "metric",
      "x": 0, "y": 0, "width": 12, "height": 6,
      "properties": {
        "region": "eu-west-1",
        "view": "timeSeries",
        "stat": "Sum",
        "period": 60,
        "metrics": [
          ["AWS/Lambda", "Errors", "FunctionName", "checkout-api"],
          ["AWS/Lambda", "Throttles", "FunctionName", "checkout-api"]
        ]
      }
    }
  ]
}

go deeper

for a junior

Know that a CloudWatch dashboard can carry drop-down controls at the top so one dashboard serves several instances or environments, rather than copying the dashboard per target.

for a middle

Explain the two variable kinds — a property variable swapping a dimension, region or account, and a pattern variable doing a text substitution over the dashboard JSON — and where each is appropriate.

for a senior

Show that you have been burned: a variable reaching only some widgets looks like it worked, so verify every graph moved, and populate options from a search so the picker never omits a new resource.

for a principal

Own dashboards as versioned code — one parameterised definition deployed everywhere via PutDashboard, so improvements land once and no team is navigating a drifted copy mid-incident.

## The problem Dashboard sprawl is the normal failure mode of CloudWatch. A team builds a good dashboard for production in one region, copies it for staging, copies it again for a second region, and from then on every improvement has to be applied N times. In practice it is applied once, the copies drift, and the dashboard someone opens during an incident is the stale one. **Dashboard variables** exist to make the copies unnecessary: one dashboard definition, plus controls at the top that repoint it. ## Where variables live A variable is declared in the dashboard body alongside `widgets`: ```json { "variables": [ { "type": "property", "property": "region", "inputType": "select", "id": "region", "label": "Region", "defaultValue": "eu-west-1", "values": [ { "value": "eu-west-1", "label": "Ireland" }, { "value": "us-east-1", "label": "N. Virginia" } ] } ], "widgets": [] } ``` `inputType` controls the rendering — a select drop-down, a radio group, or a free-text input for values you cannot enumerate. The control appears above the widgets, and selection is reflected in the dashboard URL, so a link you paste into an incident channel carries the selection with it. ## Property variables A property variable names a **widget property** and swaps its value everywhere it appears. The property can be: - a **metric dimension** — `InstanceId`, `FunctionName`, `TableName`, `LoadBalancer`; - **`region`** — one dashboard, a region picker; - the **account**, once cross-account observability is in place. This is the precise, well-behaved option: CloudWatch understands the property it is substituting, so it knows which widgets are affected and leaves the rest alone. A dashboard whose widgets all graph `AWS/Lambda` metrics dimensioned on `FunctionName` becomes a per-function dashboard with one drop-down. ## Pattern variables A pattern variable does a **string substitution over the dashboard JSON**. You give it a string that appears in the definition — say `prod` — and each selected value replaces it. That reaches things a property variable cannot: log group names inside a `log` widget's query, a substring of an ARN, a title, a namespace suffix. It is powerful and correspondingly sharp. The match is textual, so a pattern like `prod` also hits `product-service` and `reproducible`. Choose a pattern that is unambiguous within the document — an environment segment that appears as `/prod/` or `-prod-` rather than a bare word — and read the preview before saving. ## Populating the values Two sources: - **A static list**, enumerated in `values`. Fine for a small, stable set such as three environments. - **A search**, so the drop-down is populated from the metrics that actually exist. This matters for anything dynamic — instances, queues, functions — because a hardcoded list rots the moment something is created or destroyed, and worse, silently omits the new thing you are trying to look at. ## What it does and does not fix What you gain is a single definition to maintain, a single place to add a widget, and a URL that carries a selection. What it is not is a data join: a variable repoints widgets, it does not put two environments side by side on one graph. For a genuine comparison you still want either explicit widgets per environment or a metric search expression that returns several series. The other limit is silent scope. A variable only affects widgets whose JSON contains the property or the pattern. Add a widget by hand with a hardcoded dimension and it will keep showing production while the picker says staging — a genuinely dangerous failure, because the dashboard looks like it responded. Whenever you change a variable, confirm that every widget's title or data actually moved. ## Operational advice Keep the dashboard body in source control and deploy it with `PutDashboard`. Variables reduce the number of documents to *one*; version control makes that one reviewable. The combination is what turns a wall of console-drawn graphs into something a team can maintain.

  • When would you reach for a pattern variable instead of a property variable?
    When the thing you want to swap is not a widget property CloudWatch understands — a log group name inside a Logs Insights query, a substring of an ARN, part of a widget title. A property variable can only target real properties such as a dimension, region or account; a pattern variable substitutes text anywhere in the dashboard JSON, at the cost of matching more broadly than you intend.
  • Someone selects staging in the picker but one graph still shows production traffic. What happened?
    That widget's JSON does not contain the property or the pattern the variable targets — typically because it was hand-edited with a hardcoded dimension or an ARN in a different shape. The variable simply does not reach it, and nothing warns you. Fix the widget so its value matches what the variable substitutes.
  • Why prefer a search-populated variable over a hardcoded list of values?
    Because a hardcoded list rots. Instances, queues and functions come and go, and the list will silently omit whatever was created most recently — usually the thing you are investigating. Populating options from a metric search means the picker always reflects what currently reports data.

saying these in an interview costs you the question

  • Copying a dashboard per environment and calling it templating
  • Thinking a variable joins several environments onto one graph
  • Assuming a pattern variable matches only whole words
  • Hardcoding a value list for a set that changes constantly
  • Not verifying that every widget responded to the selection

context