Grafana SQL Data Source (Postgres/MySQL) Dashboards Prompt
Build Grafana dashboards on Postgres or MySQL data sources using SQL macros ($__timeFilter, $__timeGroup) for time series and tables.
- Target user
- SREs and data engineers turning relational data into Grafana panels
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior observability engineer fluent in Grafana's SQL data sources and its macro system.
I will provide:
- The database engine (Postgres or MySQL) and schema
- Tables/columns to visualize
- Panels or SLOs to build
Your job:
1. **Configure the datasource** with a least-privilege read-only role and TLS; set `sslmode` for Postgres and the connection limits.
2. **Time series queries**: return a `time` column plus metric columns, and always bound with `$__timeFilter(created_at)` and bucket with `$__timeGroup(created_at, $__interval)` (Postgres) or `$__timeGroupAlias` for named output.
3. **Table queries**: use Format = Table, alias columns cleanly, and rely on transformations for joins across queries.
4. **Macros**: apply `$__timeFrom()`, `$__timeTo()`, `$__unixEpochFilter()`, and `$__interval` correctly per engine — Postgres and MySQL differ.
5. **Template variables**: drive dropdowns with SQL like `SELECT DISTINCT service FROM deploys ORDER BY 1` and reference them as `WHERE service IN ($service)`.
6. **Parameterization safety**: quote multi-value variables and avoid SQL injection by using `${var:sqlstring}` formatting.
7. **Performance**: index the time column, avoid `SELECT *`, and pre-aggregate with `$__timeGroup` rather than pulling raw rows.
8. **Provisioning**: define the datasource in YAML with `secureJsonData` for the password.
Mark DESTRUCTIVE: granting write/DDL privileges to the Grafana role, running unbounded queries without $__timeFilter, pointing at a primary instead of a read replica.
---
Engine/schema: [DESCRIBE]
Tables/columns: [DESCRIBE]
Panels/SLOs: [DESCRIBE]
Why this prompt works
Grafana’s SQL data sources are powerful but the macro layer ($__timeFilter, $__timeGroup) is where people slip — they either omit it and full-scan a table, or use the Postgres form against MySQL. This prompt forces engine-aware macro usage, read-only auth, and pre-aggregation so relational panels stay fast and safe.
How to use it
- Name the engine so the assistant uses the correct macro variants.
- Share the schema and indexes so it can pre-aggregate against indexed columns.
- Describe the panel type (time series vs table) to pick the Format setting.
- Ask for the read-only grant and provisioning YAML.
Useful commands
-- Least-privilege read-only role (Postgres)
CREATE ROLE grafana_ro LOGIN PASSWORD 'REDACTED';
GRANT CONNECT ON DATABASE appdb TO grafana_ro;
GRANT USAGE ON SCHEMA public TO grafana_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO grafana_ro;
# Health-check the datasource via Grafana API
curl -s -H "Authorization: Bearer $GRAFANA_TOKEN" \
http://localhost:3000/api/datasources/uid/pg-app/health
Example config
# provisioning/datasources/postgres.yaml
apiVersion: 1
datasources:
- name: App Postgres
type: postgres
uid: pg-app
access: proxy
url: replica.db.internal:5432
user: grafana_ro
jsonData:
database: appdb
sslmode: require
postgresVersion: 1600
maxOpenConns: 5
timescaledb: false
secureJsonData:
password: ${PG_GRAFANA_PASSWORD}
-- Time series panel: request rate per service, bucketed
SELECT
$__timeGroup(created_at, $__interval) AS time,
service,
count(*) AS requests
FROM request_log
WHERE $__timeFilter(created_at)
AND service IN (${service:sqlstring})
GROUP BY 1, 2
ORDER BY 1;
Common findings this catches
- Full table scans → missing
$__timeFilter. - Wrong buckets →
$__timeGroupvariant mismatched to engine. - Production impact → datasource on primary instead of replica.
- Injection risk → multi-value variable not
${var:sqlstring}. - Slow panels → no index on the time column.
- Broken table joins → should use transformations, not sub-queries.
- Credential leak → password in
jsonData.
When to escalate
- Query load impacting the database — involve DBAs and add a dedicated replica.
- Schema redesign for analytics — data engineering.
- Row-level security or PII exposure in panels — security review.
Related prompts
-
Grafana Data Source Provisioning YAML Prompt
Provision Grafana data sources as code with provisioning YAML in /etc/grafana/provisioning/datasources for reproducible, secret-safe config.
-
Grafana InfluxDB (Flux/InfluxQL) Data Source Prompt
Configure a Grafana InfluxDB data source with both Flux and InfluxQL, choosing the right query language per version and building efficient panels.
-
Grafana Table Panel Transformations Prompt
Shape Grafana table panels with transformations — join, organize, group-by, and calculations — to turn raw query frames into readable tables.