Grafana Dashboard Variables: Dynamic Filtering Without Duplicate Dashboards
Stop duplicating Grafana dashboards per environment. Learn how query and custom variables, chained filtering, and the =~ operator give you one dynamic dashboard — plus the multi-select mistake that causes 'No Data'.
03 Nov 2025, 16:01 UTC

If you're maintaining separate Grafana dashboards for production, staging, and dev — or one dashboard per service — variables eliminate that duplication. A dashboard variable is a dropdown at the top of the dashboard whose value gets injected into every panel query that references it. Change the dropdown once, and every panel re-queries with the new filter. This guide walks through a working two-variable setup (environment + service), the query syntax that makes multi-select work, and the mistakes that cause "No Data" panels.
How variables actually work
Variables are defined per dashboard under Dashboard settings → Variables. When a dashboard loads, Grafana evaluates each variable (which may mean running a query against a data source), renders the dropdowns, and substitutes the selected values into panel queries wherever it finds $variable_name or ${variable_name}. The substitution happens before the query is sent to the data source — Prometheus, Loki, or whatever you're using never sees the variable syntax, only the resolved value.
There are several variable types, but two cover most real use cases:
- Query variables — populated dynamically from a data source, e.g.
label_values(up, job)in Prometheus. The dropdown stays current as new label values appear. - Custom variables — a static, comma-separated list you type in yourself. Ideal for a small, stable set of options like environment names.
A worked example: environment and service filtering
Assume a Prometheus data source where metrics carry env and job labels. The goal: one dashboard where you pick an environment, then pick one or more services within it.
Variable 1: environment (custom)
Create a variable named env:
- Type: Custom
- Values:
production,staging,dev - Multi-value: off (you usually view one environment at a time)
Variable 2: service (query, chained to environment)
Create a variable named service:
- Type: Query
- Data source: your Prometheus instance
- Query:
label_values(up{env="$env"}, job) - Refresh: On time range change (or on dashboard load)
- Multi-value: on, and enable Include All option
Notice the $env reference inside the query. This is a chained variable: switching the environment dropdown re-runs the service query, so the service list only shows jobs that exist in the selected environment. This gives you a hierarchical drill-down without any plugins.
Referencing the variables in a panel
In a Prometheus panel, use the variables with regex match operators so multi-select works:
rate(http_requests_total{env="$env", job=~"$service"}[5m])The =~ operator matters. When multi-value or "All" is selected, Grafana renders $service as a regex alternation like (api|worker|frontend). If you use exact equality (=) with multiple values selected, the query matches nothing and the panel shows "No Data" — this is the single most common variable mistake.
For a Loki log panel the same pattern applies:
{env="$env", job=~"$service"} |= "error"Verifying the setup
After saving the dashboard:
- Confirm the
servicedropdown populates. If it's empty, run the variable's query directly in the Explore view against the same data source — the problem is almost always the label filter or the data source selection, not Grafana. - Change the
envdropdown and confirm theservicelist refreshes and panels re-query. - Select two services plus "All" and confirm panels still render. If they break only in multi-select mode, check for
=instead of=~in your queries. - Open the panel's Query inspector to see the fully interpolated query — this shows you exactly what Grafana sent after substitution, which is the fastest way to debug unexpected values.
Limits and common mistakes
- Load time. Every query variable fires a request when the dashboard loads (and chained variables fire again when their parent changes). Five or six query variables against a slow data source can add seconds to initial load. Keep variable queries cheap —
label_valuesis fine; avoid queries that scan heavy time series. - Regex escaping. If your label values contain regex metacharacters (dots, slashes), multi-value interpolation can produce patterns that match more than intended. Grafana escapes values in many interpolation contexts, but verify with the Query inspector if counts look wrong.
- Scope. Variables live on one dashboard. They are not inherited by other dashboards in the same folder. To share a setup, save the dashboard as a template or use provisioning to deploy the same JSON model in multiple places.
- URL state. Variable selections are carried in the URL as
var-env=productionparameters. This is useful for linking directly to a filtered view, but it also means a bookmarked URL can pin a stale variable value. - Ad-hoc filters vs. variables. If you need free-form filtering on arbitrary labels rather than a curated dropdown, consider an ad-hoc filter variable instead of building dozens of query variables.
Behavior described here reflects Grafana 9/10/11; the variable editor UI has shifted slightly between versions (notably the move of variables into dashboard settings and the newer "Variable editor" layout in Grafana 10+), so confirm menu locations against your installed version.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.