Terraform can manage Datadog dashboards, but it’s not just about creating them; it’s about treating your dashboards as immutable infrastructure.

Let’s see it in action. Imagine you have a critical dashboard tracking your e-commerce site’s performance. You want to ensure this dashboard is always up-to-date with the latest metrics and alerts.

provider "datadog" {
  api_key = var.datadog_api_key
  app_key = var.datadog_app_key
}

resource "datadog_dashboard" "ecommerce_performance" {
  title = "E-commerce Site Performance"
  description = "Real-time monitoring of key e-commerce metrics."

  widget {
    definition {
      type = "timeseries"
      title = "Orders per Minute"
      requests {
        q = "sum:ecommerce.orders.count{*} by {datacenter} by {status}.as_count()"
      }
      viz_type = "timeseries"
    }
  }

  widget {
    definition {
      type = "timeseries"
      title = "Revenue per Minute"
      requests {
        q = "sum:ecommerce.revenue.total{*} by {datacenter}.as_rate()"
      }
      viz_type = "timeseries"
    }
  }

  widget {
    definition {
      type = "alert_graph"
      alert_id = datadog_monitor.high_error_rate.id
      title = "High Error Rate Alert"
    }
  }
}

resource "datadog_monitor" "high_error_rate" {
  name               = "High E-commerce Error Rate"
  type               = "metric alert"
  message            = "High error rate detected on e-commerce site. @slack-channel-ecommerce"
  escalation_message = "Still high error rate. @pagerduty-ecommerce"
  query = "sum(last_15m):sum:ecommerce.requests.failed{*} by {datacenter} > 100"

  monitor_thresholds {
    critical = 100
  }

  notify_no_data    = false
  renotify_interval = 60
}

This Terraform code defines a Datadog dashboard resource. It specifies the title, description, and then dives into the widget blocks. Each widget block defines a visualization on the dashboard. Here, we have two timeseries widgets for orders and revenue, and an alert_graph widget that dynamically displays the status of a Datadog monitor. The datadog_monitor resource itself is also defined, showing how infrastructure-as-code can manage both your monitoring and your dashboards.

The core problem this solves is drift. Without code, dashboards are manually updated. Over time, they become inaccurate, incomplete, or miss critical new metrics. This Terraform configuration ensures your dashboard is a single source of truth for your e-commerce performance, versioned and auditable. The datadog_dashboard resource in Terraform maps directly to a dashboard in Datadog. When you run terraform apply, Terraform communicates with the Datadog API to create or update the dashboard to match the desired state defined in your .tf files.

Internally, Terraform uses the Datadog provider, which authenticates using your Datadog API and App keys. It then constructs API calls to Datadog’s dashboard endpoint, translating the HCL (HashiCorp Configuration Language) into the JSON structure that Datadog expects for dashboard definitions. You control the dashboard’s content, layout, and associated alerts through the HCL syntax.

The most surprising thing most people miss is how Terraform handles dashboard updates. When you modify a widget’s query or change a graph’s visualization type in your Terraform code and run terraform apply, Terraform doesn’t just append the change. It will recreate the entire dashboard resource if certain core attributes change, or perform a partial update if possible. This means your dashboard is treated as an immutable object: if you want to change its fundamental structure or a key component, you’re essentially replacing it with a new version, ensuring a clean state. This immutability is key to preventing subtle, hard-to-debug configuration drift.

The next step is integrating this into a CI/CD pipeline for automated deployment of dashboard changes.

Want structured learning?

Take the full Datadog course →