Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 10 min read

Terraform Check Blocks With Scoped Data Sources for Live Health Assertions

Terraform check blocks can carry their own scoped data source to probe live infrastructure as a non-blocking warning. Here's how to assert runtime health without failing every plan.

  • #terraform
  • #ai
  • #check-blocks
  • #data-sources
  • #assertions

Most Terraform validation answers the question “is this config internally consistent?” — variable types, preconditions, postconditions. None of it answers a different question that operators actually care about: “is the thing I just deployed actually working right now?” Is the endpoint returning 200? Is the certificate close to expiry? Does the DNS record resolve?

check blocks were built for exactly that, and they have a feature that makes them surprisingly powerful: a data source scoped to the check itself, so you can probe live state without touching the rest of your config.

Check blocks warn — they don’t block

The first thing to internalize is that a check block is non-blocking. When its assertion fails, you get a warning, the run continues, and the apply still succeeds. This trips people up because they expect a gate. It is not a gate.

That’s a feature, not a bug, once you frame it correctly:

  • Use a check block when you want to know something is off, but not stop the deploy.
  • Use a precondition or postcondition when you want to stop a dangerous apply.

If your assertion must block — “refuse to apply if this AMI is deprecated” — a check is the wrong tool. For “warn me on every plan if the production endpoint is unhealthy,” it’s exactly right. Our check blocks and assertions prompt helps you make that call deliberately.

The scoped data source

Here’s the part that’s easy to miss: a check block can contain its own data source, visible only inside that check. It’s evaluated when the check runs and can’t be referenced anywhere else in your config, which keeps your dependency graph clean.

check "health_endpoint" {
  data "http" "app" {
    url = "https://${aws_lb.app.dns_name}/healthz"
  }

  assert {
    condition     = data.http.app.status_code == 200
    error_message = "Health endpoint returned ${data.http.app.status_code}, expected 200."
  }
}

Because the data "http" lives inside the check, it doesn’t pollute the broader config and won’t create accidental dependencies elsewhere. It runs after apply, hits the live endpoint, and surfaces a warning if the status isn’t 200.

Certificate expiry as a continuous warning

A common, high-value use is catching certificates before they expire — the kind of thing that should never page you at 3 a.m. but always seems to:

check "cert_expiry" {
  data "tls_certificate" "site" {
    url = "https://example.com"
  }

  assert {
    condition = timecmp(
      timestamp(),
      timeadd(data.tls_certificate.site.certificates[0].not_after, "-720h")
    ) < 0
    error_message = "TLS certificate for example.com expires within 30 days — rotate it."
  }
}

Every plan now quietly checks that you have at least 30 days of runway, and warns the moment you don’t. No external monitor, no separate cron — it rides along with the runs you’re already doing.

Handle the transient case

Because checks run after apply, a freshly created endpoint might not be live yet, and the check will warn on that first run. That’s usually correct behavior — a warning, not a failure — and the next plan will pass once the service is up. If a not-yet-ready state would genuinely be dangerous to proceed past, that’s your signal to promote the assertion to a postcondition on the resource instead, where it can actually block.

Keep the probe cheap

A check runs on every plan. If the scoped data source is slow, rate-limited, or has side effects, you’ve just taxed every run your whole team makes. Keep probes fast, read-only, and side-effect-free. Don’t hammer an external API that throttles you; don’t call something that mutates state. A check that slows CI by ten seconds on every plan will get deleted out of frustration, taking its safety value with it.

Draft the assertion with AI, prove it in a sandbox

The fiddly part is usually the condition expression — date math, status comparisons, digging into a data source’s attributes. That’s worth handing to an AI assistant and then proving in a non-production workspace. A prompt like:

Write a Terraform check block with a scoped data source that warns when the TLS cert at https://example.com is within 30 days of expiry. Use the tls_certificate data source. Give me the assert condition and an error message an on-call engineer can act on. Note any case where the probe itself could error.

A solid answer returns the block above plus:

Caveat: if example.com is unreachable, data.tls_certificate errors and the check reports a problem — which is arguably correct, but if you only care about expiry, consider wrapping the probe so an unreachable host doesn’t masquerade as an expiry warning.

That nuance — distinguishing “cert expiring” from “host down” — is exactly what you want a human to verify against a real apply before trusting the check. Our check block scoped data source prompt is built around producing that and confirming it fires only when it should.

When checks earn their place

Reach for check blocks with scoped data sources when you want a lightweight, in-pipeline health signal that warns without blocking: endpoint reachability, cert runway, DNS resolution, basic SLO sanity. Keep the probes fast, let AI draft the gnarly conditions, and verify each one in a sandbox so it warns on real problems and stays silent otherwise.

What you should not do is reach for them as a safety gate — that’s what precondition and postcondition are for. Used for the right job, checks give you a quiet, continuous “is it actually working?” signal that travels with your normal runs. For the full range of Terraform validation tools, browse our Terraform guides.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.