tutorial

Monitoring CDKTF Infrastructure with Vigilmon: Deployed Endpoint Health, State Backend Availability, TLS Certificate Alerts & Deploy Pipeline Heartbeats

How to monitor CDKTF-managed infrastructure with Vigilmon — monitoring the endpoints CDKTF provisions, Terraform state backend health, TLS certificate expiry on deployed resources, and heartbeat monitoring for CDKTF deployment pipelines.

CDK for Terraform (CDKTF) lets you define cloud infrastructure using TypeScript, Python, Go, Java, or C# instead of HCL — you write programs that synthesize Terraform configurations and apply them via the Terraform CLI. Teams use CDKTF to manage load balancers, Kubernetes clusters, databases, API gateways, and every other piece of cloud infrastructure. When a CDKTF-managed resource goes down — a load balancer provisioned by your CDKTF stack, an API Gateway endpoint defined in TypeScript, a Kubernetes cluster stood up by a Go CDKTF construct — the application depending on it fails. When the Terraform state backend becomes unavailable, no CDKTF deployment can run safely. Vigilmon gives you external visibility into the endpoints CDKTF provisions, the state backends CDKTF depends on, and the deployment pipelines that run CDKTF apply.

What You'll Build

  • HTTP monitors on the endpoints CDKTF provisions (load balancers, API gateways, app servers)
  • SSL certificate monitors for CDKTF-managed HTTPS endpoints
  • HTTP monitors on the Terraform state backend
  • Heartbeat monitors for CDKTF deployment pipelines
  • Alerting runbook mapping CDKTF infrastructure failure modes to the right resources

Prerequisites

  • CDKTF installed (npm install -g cdktf-cli)
  • One or more CDKTF stacks deployed to AWS, GCP, Azure, or a self-hosted provider
  • A free account at vigilmon.online

Step 1: Understand What to Monitor in a CDKTF Deployment

CDKTF provisions infrastructure, but what Vigilmon monitors is the infrastructure CDKTF creates — plus the operational dependencies of CDKTF itself:

# List your deployed CDKTF stacks
cdktf output --stack my-stack
# Expected: Terraform outputs, including public endpoints

# Get all outputs from a stack (useful for extracting monitor URLs)
cdktf output --stack my-stack --json
# Expected: JSON with all stack outputs

# Check the Terraform state for a CDKTF stack
terraform show -json .terraform/state 2>/dev/null || \
  aws s3 cp s3://my-tfstate-bucket/my-stack/terraform.tfstate - | jq '.resources[].type' | sort | uniq -c
# Expected: list of resource types managed by the stack

The key health surfaces for CDKTF-managed infrastructure:

  1. The public endpoints the stack exposes (load balancers, API gateways, App Service URLs)
  2. TLS certificates on those endpoints
  3. The Terraform state backend (S3, GCS, Azure Blob, Terraform Cloud)
  4. The CDKTF deployment pipeline (CI/CD jobs that run cdktf deploy)

Step 2: Monitor the Endpoints CDKTF Provisions

Extract your CDKTF stack's output URLs and add Vigilmon monitors for each:

// In your CDKTF stack (TypeScript example)
// Export the endpoint as a Terraform output so you can retrieve it
new TerraformOutput(this, 'api_gateway_url', {
  value: apiGateway.url,
  description: 'API Gateway endpoint — monitor this URL with Vigilmon',
});

new TerraformOutput(this, 'load_balancer_dns', {
  value: alb.dnsName,
  description: 'Application Load Balancer DNS name',
});
# After deploying, extract the output URLs
cdktf output --stack my-api-stack --json | jq '.api_gateway_url.value'
# Output: https://abc123.execute-api.us-east-1.amazonaws.com/prod

cdktf output --stack my-web-stack --json | jq '.load_balancer_dns.value'
# Output: my-alb-1234567890.us-east-1.elb.amazonaws.com

API Gateway Endpoint

  1. Log in to VigilmonAdd Monitor → HTTP.
  2. URL: https://abc123.execute-api.us-east-1.amazonaws.com/prod/health.
  3. Check interval: 60 seconds.
  4. Response timeout: 15 seconds.
  5. Expected status: 200.
  6. Label: CDKTF API Gateway (prod).
  7. Click Save.

Application Load Balancer

  1. Add Monitor → HTTP.
  2. URL: https://my-alb-1234567890.us-east-1.elb.amazonaws.com/health.
  3. Check interval: 60 seconds.
  4. Expected status: 200.
  5. Label: CDKTF ALB health check.
  6. Click Save.

Add a TCP monitor to detect network-layer failures on the load balancer:

  1. Add Monitor → TCP.
  2. Host: my-alb-1234567890.us-east-1.elb.amazonaws.com.
  3. Port: 443.
  4. Label: CDKTF ALB TCP (443).
  5. Click Save.

Step 3: Add Health Endpoints to CDKTF-Managed Applications

If your CDKTF stack provisions an application (EC2, ECS, Lambda, App Service), add a /health endpoint to each service and reference it in your stack outputs:

// TypeScript CDKTF example — ECS service with health check output
const service = new EcsService(this, 'api-service', {
  cluster: cluster.arn,
  taskDefinition: taskDef.arn,
  healthCheckGracePeriodSeconds: 60,
});

// Target group health check
new LbTargetGroup(this, 'api-tg', {
  port: 8080,
  protocol: 'HTTP',
  targetType: 'ip',
  healthCheck: {
    path: '/health',
    healthyThreshold: 2,
    unhealthyThreshold: 3,
    interval: 30,
  },
});

new TerraformOutput(this, 'health_endpoint', {
  value: `https://${alb.dnsName}/health`,
});
# Python CDKTF example — Lambda function with health endpoint
from cdktf_cdktf_provider_aws.lambda_function import LambdaFunction
from cdktf import TerraformOutput

health_fn = LambdaFunction(self, "health-check",
    function_name="health-check",
    handler="index.handler",
    runtime="python3.11",
)

TerraformOutput(self, "health_function_url",
    value=health_fn.function_url,
    description="Lambda function URL for health checks"
)

Add the output URL to Vigilmon as an HTTP monitor after cdktf deploy completes.


Step 4: Monitor the Terraform State Backend

CDKTF stores Terraform state in a remote backend — usually S3, GCS, Azure Blob, or Terraform Cloud. If the state backend becomes unavailable, no deployment can safely run: cdktf deploy will fail to lock or read the state, and your infrastructure is effectively frozen:

# Test S3 state backend reachability
aws s3api head-object \
  --bucket my-tfstate-bucket \
  --key my-stack/terraform.tfstate
# Expected: 200 with object metadata

# S3 bucket website endpoint (if enabled)
curl -I https://my-tfstate-bucket.s3.amazonaws.com/
# Expected: 200 or 403 (bucket exists and is reachable)

# Terraform Cloud API (if using remote state)
curl https://app.terraform.io/api/v2/ping
# Expected: {"meta":{"status":"ok"}}

# GCS state backend
gsutil stat gs://my-tfstate-bucket/my-stack/terraform.tfstate
# Expected: metadata output (no error = accessible)

For Terraform Cloud state:

  1. Add Monitor → HTTP.
  2. URL: https://app.terraform.io/api/v2/ping.
  3. Check interval: 300 seconds (5 minutes — Terraform Cloud is a managed service).
  4. Expected status: 200.
  5. Keyword: ok.
  6. Label: Terraform Cloud API.
  7. Click Save.

For self-hosted Terraform Enterprise:

  1. Add Monitor → HTTP.
  2. URL: https://tfe.example.com/api/v2/ping.
  3. Check interval: 60 seconds.
  4. Expected status: 200.
  5. Label: Terraform Enterprise API.
  6. Click Save.

For S3/GCS-backed state, create a monitoring Lambda or Cloud Function that checks bucket accessibility and sends a Vigilmon heartbeat:

# lambda_state_check.py — runs every 5 minutes
import boto3
import urllib.request

def handler(event, context):
    s3 = boto3.client('s3')
    try:
        s3.head_object(
            Bucket='my-tfstate-bucket',
            Key='my-stack/terraform.tfstate'
        )
        # State file is accessible — ping Vigilmon
        urllib.request.urlopen('https://vigilmon.online/heartbeat/abc123', timeout=5)
        return {'status': 'ok'}
    except Exception as e:
        print(f"State backend check failed: {e}")
        return {'status': 'error', 'error': str(e)}

Step 5: Monitor TLS Certificates on CDKTF-Managed Domains

CDKTF stacks often provision ACM certificates (AWS), managed SSL certificates (GCP), or App Service certificates (Azure). These auto-renew, but auto-renewal can fail due to DNS propagation issues or validation timeouts:

# Check ACM certificate status
aws acm describe-certificate --certificate-arn arn:aws:acm:us-east-1:123:certificate/abc123 \
  | jq '.Certificate.Status, .Certificate.NotAfter'
# Expected: "ISSUED" and a date well in the future

# Check the live certificate on your endpoint
echo | openssl s_client -connect api.example.com:443 2>/dev/null | \
  openssl x509 -noout -dates
# notAfter=Dec 31 00:00:00 2026 GMT

# For CDKTF stacks using custom domains, check all provisioned domains
cdktf output --stack my-stack --json | jq 'to_entries[] | select(.key | contains("domain")) | .value.value'
  1. Add Monitor → SSL Certificate.
  2. Domain: api.example.com (or the domain your CDKTF stack provisions).
  3. Alert when expiry is within: 30 days.
  4. Alert again: 14 days, 7 days, 3 days, 1 day.
  5. Click Save.

Add a certificate monitor for each public domain your CDKTF stacks manage. A 30-day alert window gives you time to investigate ACM validation failures, re-trigger certificate issuance, or update DNS records before users are affected.


Step 6: Heartbeat Monitoring for CDKTF Deployment Pipelines

CDKTF deployment pipelines (cdktf deploy) run in CI/CD systems on a schedule or triggered by commits. If the pipeline stops running — due to a CI/CD system outage, a broken cron, or a failed dependency update — your infrastructure drifts from its desired state silently:

GitHub Actions CDKTF Pipeline

# .github/workflows/cdktf-deploy.yml
name: CDKTF Deploy

on:
  push:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'  # Nightly drift check

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: CDKTF Deploy
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: |
          npx cdktf deploy --auto-approve my-stack

      - name: Ping Vigilmon heartbeat
        if: success()
        run: curl -s https://vigilmon.online/heartbeat/abc123

Set up the heartbeat monitor:

  1. In Vigilmon → Add Monitor → Cron Heartbeat.
  2. Expected interval: 1500 minutes (25 hours — covers the nightly schedule with buffer).
  3. Copy the heartbeat URL and add it to the pipeline.
  4. Label: CDKTF nightly deploy.
  5. Click Save.

GitLab CI CDKTF Pipeline

# .gitlab-ci.yml
cdktf-deploy:
  image: node:20
  script:
    - npm ci
    - npx cdktf deploy --auto-approve my-stack
    - curl -s https://vigilmon.online/heartbeat/def456
  only:
    - main
    - schedules

cdktf diff Drift Detection

Run a nightly diff to detect infrastructure drift without applying changes:

#!/bin/bash
# cdktf-drift-check.sh

cdktf diff my-stack 2>&1 | tee /tmp/drift-output.txt
EXIT_CODE=$?

if [ ${EXIT_CODE} -eq 0 ]; then
  # No drift — infrastructure matches desired state
  curl -s https://vigilmon.online/heartbeat/ghi789
else
  # Drift detected — do not ping heartbeat; Vigilmon fires after interval
  echo "Drift detected:"
  cat /tmp/drift-output.txt
fi
  1. Add Monitor → Cron Heartbeat.
  2. Expected interval: 1500 minutes.
  3. Label: CDKTF drift detection.
  4. Click Save.

Step 7: Automate Monitor Creation from CDKTF Outputs

For large CDKTF deployments with many stacks, automate Vigilmon monitor creation from stack outputs using the Vigilmon API:

// post-deploy.ts — run after cdktf deploy
import { execSync } from 'child_process';

const STACKS = ['api-stack', 'web-stack', 'worker-stack'];
const VIGILMON_API_KEY = process.env.VIGILMON_API_KEY!;
const VIGILMON_API = 'https://vigilmon.online/api';

for (const stack of STACKS) {
  const outputs = JSON.parse(
    execSync(`cdktf output --stack ${stack} --json`).toString()
  );

  // Find all output keys ending in _url or _endpoint
  const endpoints = Object.entries(outputs)
    .filter(([key]) => key.endsWith('_url') || key.endsWith('_endpoint'))
    .map(([key, val]: [string, any]) => ({ key, url: val.value }));

  for (const { key, url } of endpoints) {
    if (!url.startsWith('http')) continue;

    const response = await fetch(`${VIGILMON_API}/monitors`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${VIGILMON_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        type: 'http',
        url,
        label: `${stack}/${key}`,
        interval: 60,
        expected_status: [200],
      }),
    });

    console.log(`Created monitor for ${stack}/${key}: ${url}`);
  }
}

Run this script as the final step in your CDKTF deployment pipeline to keep Vigilmon monitors in sync with your infrastructure.


Step 8: Configure Alerting

In Vigilmon under Settings → Notifications, configure alert channels and response runbooks:

| Monitor | Trigger | Immediate action | |---|---|---| | CDKTF API Gateway / ALB | Non-200 or timeout | Check AWS/GCP console for health check failures; check CDKTF stack outputs for the correct URL; run cdktf diff to check for drift | | Terraform Cloud / TFE API | Non-200 | Check Terraform Cloud status page; state locking is unavailable; do not run cdktf deploy until resolved | | TLS certificate | < 30 days | Check ACM certificate status: aws acm list-certificates; look for PENDING_VALIDATION status; fix DNS validation records | | CDKTF deploy heartbeat | Missed ping | Check CI/CD pipeline for failures; verify credentials are valid; check for Terraform plan errors in the last run | | CDKTF drift detection heartbeat | Missed ping | Run cdktf diff my-stack manually; check for infrastructure drift; verify the diff script runs in CI | | TCP (443) on ALB | Connection refused | Check security groups, NACLs, and load balancer listener configuration; check for misconfigured CDKTF network resources |


Common CDKTF Infrastructure Failure Modes and What Vigilmon Catches

| Scenario | Vigilmon signal | |---|---| | CDKTF stack deleted accidentally | All endpoint monitors fire simultaneously | | ALB health check misconfiguration after CDKTF update | ALB HTTP monitor fires with 502 or 503 | | ACM certificate validation stuck (DNS record missing) | SSL monitor fires at 30-day threshold before certificate expires | | Terraform state backend S3 bucket deleted | State backend heartbeat fires; cdktf deploy fails with NoSuchBucket error | | CDKTF deploy pipeline broken (dependency update) | Deploy heartbeat fires; infrastructure drifts from desired state silently | | Security group change locks out HTTPS traffic | TCP and HTTP monitors fire together; SSH access for debugging may also be blocked | | API Gateway stage deleted outside of CDKTF | HTTP monitor fires; drift detected on next cdktf diff run | | Load balancer in wrong region after stack rename | TCP monitor fires with connection refused; endpoints unreachable | | Terraform Cloud API outage | State backend HTTP monitor fires; all CDKTF deployments blocked | | Lambda function cold start timeout misconfiguration | HTTP monitor fires intermittently with 504; increase responseTimeout in CDKTF |


CDKTF gives you the expressiveness of a programming language to define cloud infrastructure — but the infrastructure it provisions still needs external monitoring to confirm it's actually running. Vigilmon gives you external visibility into the endpoints CDKTF creates, the state backends it depends on, and the pipelines that keep it running. When a security group misconfiguration locks out HTTPS traffic to your CDKTF-managed load balancer, or a Terraform Cloud API outage freezes all your deployments, Vigilmon alerts you before the downstream impact reaches your users or your engineering team.

Start monitoring your CDKTF infrastructure in under 5 minutes — register free at vigilmon.online.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →