Using Grafana JSON Model — HowTo

Yasoob Haider
3 min readMay 27, 2021

Maybe it is just me but every couple of weeks I would find myself wanting to edit a large Grafana dashboard. Usually it would involve something like copying 10 panels (graphs) from one dashboard to another. Or copying them on the same dashboard but with some parameter modified.

While repeated rows provide a simple way to create the same set of graphs for different variables, they are not very flexible. For example, we cannot set an alert on some metric for each of the repeated rows. If we set an alert, it would fire multiple times for the panels in the first row itself.

Alternatively, we can create each panel again. But doing this will be painfully slow and prone to errors. Here I’ll walk through an example JSON which I’ll modify to copy a bunch of graphs to make a fully functional Grafana dashboard.

So let’s start.

The dashboard I’ll create will have a bunch of metrics like p50, p90, p99 response times, Healthy host count, Unhealthy host count, Active connections, Active requests and so on. These metrics need to be plotted for multiple clusters.

The abstract hierarchy of the final dashboard would be something like this:

  • cluster1
    - p50 panel
    - p90 panel
    - p99 panel
    - …
  • cluster2
    - p50 panel
    - …
  • cluster3
    - p50 panel
    - …

We start with creating all the panels for cluster1. This step has to be done manually. Although even here if few panels have almost the same query, alerts, etc, you can create one panel and then use theCopy option of the panel to create copies and then edit parts of them.

Fig 1

Your dashboard would look something like Fig 1 at this point.

Collapse the Cluster1 row. Save the dashboard.

Now comes the fun part. Go to Settings of the dashboard and click on JSON Model.

Copy the JSON to any editor of your choice. I prefer Sublime Text.

Now let’s say all the queries of cluster2 can be formed from cluster1 queries by just doing a simple replace. This is usually the case with related clusters. For example, two different services will have a label on their timeseries like service_name. We are basically replacing the value for this label.

Steps to copy:

  • Find the JSON configuration for Cluster1. It should look something like this:
"collapsed": true,
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 16
"id": 18,
"panels": [...]
"title": "Cluster1",
"type": "row"

The panels array would contain the graphs we want to copy. Each panel looks something like this (irrelevant key-values hidden).

"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 17
"id": 59,

Copy the whole config for Cluster1 to a separate file.

  • Find the maximum id of all the panels that are currently present in the original JSON config. We will give ids starting from maxid+1 to all the panels for Cluster2. Replace ids for the panels in the copied config 1-by-1.
  • Then we need to update the gridPos values. If this is not done correctly, the panels in the resulting dashboard will be all over the place. To do this, find the max y value in Cluster1. Adding the h (height) in the gridPos of the panel with max y value plus 1 will be the starting y coordinates for Cluster2(let’s call this y2). Also find the y value for the row Cluster1(let’s call it y1). Replace the y values in the copied Cluster1 config with y+y2-y1.
  • Do a Find and Replace of cluster1 with cluster2 to fix the queries.
  • Append this config after the config for Cluster1 in the original config.
  • Increase the version value near the end of the config.
  • Copy the config back to JSON model on the dashboard and press Save.

And that’s it! Your dashboard should look something like Fig 2.

Fig 2

To create more copies of the cluster just follow the same steps as above.

Tip: Sometimes you may mess up the JSON format. Run a JSON validator before pasting the config.