Choosing Between Grafana File‑Based Dashboard Provisioning and the HTTP API
A decision guide that compares file‑based and API‑driven dashboard provisioning in Grafana, shows a concrete YAML and curl example, and lists validation steps.
02 Aug 2025, 06:21 UTC

Decision and constraints
You need a repeatable way to provision Grafana dashboards that works in HA clusters, integrates with CI/CD, and avoids manual UI steps. The solution must be reproducible, support version control, and allow updates without requiring a human to click through the Grafana UI.
Constraints
- Reproducible across dev, staging, and production environments.
- Works in a Grafana HA cluster (multiple nodes sharing the same configuration).
- Allows automated updates via CI/CD pipelines.
- Does not require manual dashboard creation or editing in the UI.
Comparison of supported options
| Option | Declarative | Runtime flexibility | Setup complexity | Idempotency | Required permissions |
|---|---|---|---|---|---|
File‑based provisioning (YAML in provisioning/dashboards) |
Yes – dashboard source is a static JSON file tracked in Git. | Low – changes only take effect on Grafana restart or when the filesystem watcher is enabled. | Low – place YAML and JSON files in the provisioning folder and reference the folder in grafana.ini. |
Yes – Grafana reconciles the file state on each start/reload. | File read access for the Grafana process; no API token needed. |
HTTP API provisioning (POST /api/dashboards/db) |
No – you send an imperative request each time you want to create or update. | High – you can update dashboards on‑the‑fly, per‑dashboard, and from any host that can reach the API. | Medium – you need to manage an API key, handle duplicate detection, and write idempotent scripts. | Conditional – you must design your script to be idempotent (e.g., check existing UID before posting). | API key with at least Dashboards:Edit scope (or admin token). |
Trade‑offs
File‑based provisioning is ideal when you want a fully declarative setup that can be version‑controlled alongside application code. The dashboard appears automatically when Grafana starts or when the filesystem watcher picks up changes. The downside is that you must restart Grafana (or enable and trust the watcher) for updates, which can be inconvenient in tightly controlled HA environments where rolling restarts are undesirable.
HTTP API provisioning gives you the ability to push dashboards whenever your CI/CD pipeline runs, without touching the Grafana process. This works well for ephemeral environments or when you need to apply dashboard changes as part of a larger deployment script. However, you must take care of duplicate dashboard creation, securely store and rotate the API key, and ensure your update script is idempotent to avoid creating multiple versions of the same dashboard.
Concrete implementation example
Below is a minimal file‑based setup and the equivalent API call that provisions the same dashboard.
File‑based provisioning
- Create the provisioning folder (if it does not exist):
# Run on the host where Grafana is installed, with sufficient privileges to write to /etc/grafana
sudo mkdir -p /etc/grafana/provisioning/dashboards
- Add a YAML file that tells Grafana where to find dashboard JSON files:
# File: /etc/grafana/provisioning/dashboards/dashboard.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: false
updateIntervalSeconds: 10 # how often Grafana checks for filesystem changes
options:
path: /etc/grafana/provisioning/dashboards
- Place the dashboard JSON (example: a simple stat panel) in the same folder:
# File: /etc/grafana/provisioning/dashboards/my-stat-dashboard.json
{
"dashboard": {
"id": null,
"uid": "my-stat-dashboard",
"title": "My Stat Dashboard",
"tags": ["example"],
"timezone": "browser",
"schemaVersion": 38,
"version": 1,
"refresh": "5s",
"panels": [
{
"type": "stat",
"title": "Example Stat",
"gridPos": { "x": 0, "y": 0, "w": 12, "h": 8 },
"targets": [
{ "refId": "A", "expr": "up", "legendFormat": "{{instance}}" }
]
}
]
},
"overwrite": true
}
- Ensure Grafana knows where to look for provisioning files (add to
grafana.inior override via environment):
[paths]
provisioning = /etc/grafana/provisioning
- Restart Grafana (or enable the filesystem watcher as shown in the YAML):
# Example using systemd
sudo systemctl restart grafana-server
HTTP API provisioning
Assuming you have an API key with the Dashboards:Edit scope stored in the environment variable GRAFANA_API_KEY:
# Variables – replace with your actual values
GRAFANA_HOST="https://grafana.example.com"
DASHBOARD_JSON="/path/to/my-stat-dashboard.json" # same JSON as above
curl -X POST "${GRAFANA_HOST}/api/dashboards/db" \
-H "Authorization: Bearer ${GRAFANA_API_KEY}" \
-H "Content-Type: application/json" \
-d @${DASHBOARD_JSON}
The API returns a JSON object containing the dashboard’s uid, slug, and a status of success on a 200 OK response.
Validation and practical checks
File‑based provisioning
- Check Grafana logs for a line similar to:
t=2026-10-13T02:05:12Z lvl=info msg="Loading dashboard from provisioning file" logger=provisioning.dashboard uid=my-stat-dashboard
- In the Grafana UI, navigate to Manage → Dashboards and verify that a dashboard with UID
my-stat-dashboardappears. - Open the dashboard and confirm the panel matches the JSON you placed in
provisioning/dashboards.
HTTP API provisioning
- After running the
curlcommand, verify the HTTP response code is200and the JSON contains"status":"success". - Fetch the dashboard via the API to ensure it was stored correctly:
curl -s "${GRAFANA_HOST}/api/dashboards/uid/my-stat-dashboard" \
-H "Authorization: Bearer ${GRAFANA_API_KEY}"
Compare the returned dashboard object with the original JSON you posted (ignoring server‑generated fields like id and version). If they match, the provisioning succeeded.
Limitations and how to mitigate them
- File‑based: If the filesystem watcher is disabled (default in some distributions), changes require a Grafana restart. To avoid downtime, enable
updateIntervalSecondsin the YAML (as shown) or use a rolling restart strategy in your HA cluster. - API: Repeated POST calls without idempotency checks can create duplicate dashboards with different UIDs. Mitigate by first checking
GET /api/dashboards/uid/and only posting if the dashboard is missing or needs an update, or by using theoverwriteflag in the JSON payload. - API keys must be scoped narrowly (
Dashboards:Edit) and rotated regularly to reduce exposure.
By following the steps above you can choose the provisioning method that best fits your operational constraints and validate that dashboards are correctly loaded into Grafana.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.