Pkl (pronounced "pickle") is Apple's open-source configuration language and toolchain — a typed, programmable alternative to YAML and JSON for application configuration, Kubernetes manifests, and infrastructure definitions. When you use Pkl to manage the configuration of your production services, mistakes in that configuration are what cause outages. Vigilmon gives you the external signal that tells you when a configuration change — or anything else — has taken a service down.
In this tutorial you'll set up external uptime monitoring for services managed with Pkl configuration using Vigilmon — free tier, no credit card required.
Why Pkl-managed services need external monitoring
Pkl validates your configuration types and constraints at generation time. It does not validate that the resulting configuration produces a healthy, reachable service at runtime:
- Type-valid configuration can still be wrong — a Pkl schema can enforce that
portis an integer between 1 and 65535, but it can't verify that the service actually starts on that port or that the port is reachable through your network stack - Configuration drift between environments — Pkl makes it easy to template config across environments, but a subtle environment variable or override mismatch can cause prod to diverge from staging without any Pkl validation failure
- Generated Kubernetes manifests — when Pkl generates
DeploymentandServicemanifests, a resource limit that's valid in Pkl terms can OOM-kill pods at runtime; a misconfigured readiness probe can keep pods inNotReadyindefinitely - Deployment pipeline success ≠ working service — a CI pipeline that generates Pkl config, renders it to YAML, and applies it can exit 0 while the resulting service is crash-looping
- Configuration hot-reload failures — services that reload Pkl-generated config at runtime (via file watch or signal) can fail to apply a new config silently, serving stale configuration that diverges from your source of truth
Vigilmon adds the external observability layer that Pkl's tooling deliberately doesn't cover: continuous probing of your services from multiple geographic regions, with instant alerts when something stops working.
What you'll need
- Pkl installed (
brew install pklon macOS, or download from pkl-lang.org) - A service whose configuration is managed with Pkl
- A network-accessible endpoint for that service
- A free Vigilmon account (sign up takes 30 seconds)
Step 1: Define your service configuration with Pkl and include health endpoints
Start with a typed Pkl configuration that includes your service's health check URL — making health monitoring an explicit, typed part of your service definition.
// ServiceConfig.pkl
module ServiceConfig
/// The name of this service
name: String
/// HTTP port the service listens on
port: UInt16(isBetween(1024, 65535))
/// Base URL for external access
baseUrl: String(startsWith("https://"))
/// Path for the health check endpoint
healthPath: String(startsWith("/")) = "/health"
/// Full health check URL (computed)
healthUrl: String = "\(baseUrl)\(healthPath)"
/// Vigilmon monitor name (computed)
vigilmonMonitorName: String = "pkl/\(name)"
Then instantiate it for each environment:
// config/production.pkl
import "ServiceConfig.pkl"
name = "user-api"
port = 8080
baseUrl = "https://api.yourcompany.com"
healthPath = "/healthz"
Render the configuration to JSON for use by your application:
pkl eval --format json config/production.pkl
# {
# "name": "user-api",
# "port": 8080,
# "baseUrl": "https://api.yourcompany.com",
# "healthPath": "/healthz",
# "healthUrl": "https://api.yourcompany.com/healthz",
# "vigilmonMonitorName": "pkl/user-api"
# }
Add a health endpoint to your service that matches the healthPath in your Pkl config:
// Express.js/TypeScript example
import config from './config.json'; // generated from Pkl
app.get(config.healthPath, (req, res) => {
res.json({
status: 'ok',
service: config.name,
version: process.env.npm_package_version,
ts: new Date().toISOString()
});
});
Verify it responds:
curl "$(pkl eval --format json config/production.pkl | jq -r '.healthUrl')"
# {"status":"ok","service":"user-api","version":"2.1.0","ts":"2024-01-15T10:23:00Z"}
Step 2: Set up HTTP monitoring in Vigilmon
- Log in to vigilmon.online and go to Monitors → New Monitor
- Choose HTTP / HTTPS
- Set the URL to your service's health endpoint (from your Pkl config's
healthUrlfield) - Set the check interval to 1 minute
- Under Expected response:
- Status code:
200 - (Optional) Response body contains:
"status":"ok"
- Status code:
- Save the monitor
Generating Vigilmon monitors from Pkl config
Pkl's programmability makes it practical to generate Vigilmon monitor configuration directly from your service definitions. Create a Pkl module for Vigilmon:
// VigilmonMonitor.pkl
module VigilmonMonitor
import "ServiceConfig.pkl"
/// Generate a Vigilmon API request body from a ServiceConfig
function fromServiceConfig(svc: ServiceConfig): Mapping<String, Any> = new Mapping {
["name"] = svc.vigilmonMonitorName
["type"] = "http"
["url"] = svc.healthUrl
["interval"] = 60
["expected_status"] = 200
}
Then render monitor configuration for all your services at once:
# Generate monitor configs for all services
for env_file in config/*.pkl; do
config=$(pkl eval --format json "$env_file")
health_url=$(echo "$config" | jq -r '.healthUrl')
monitor_name=$(echo "$config" | jq -r '.vigilmonMonitorName')
# Create monitor via Vigilmon API
curl -X POST "https://vigilmon.online/api/v1/monitors" \
-H "Authorization: Bearer $VIGILMON_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"name\": \"$monitor_name\", \"type\": \"http\", \"url\": \"$health_url\", \"interval\": 60, \"expected_status\": 200}"
echo "Created monitor: $monitor_name -> $health_url"
done
This approach treats your Vigilmon monitoring setup as code, derived from the same Pkl service definitions that configure your services — configuration and monitoring stay in sync automatically.
Step 3: Monitor Kubernetes services generated from Pkl manifests
Pkl is frequently used to generate Kubernetes manifests. When a Pkl-generated manifest deploys a Kubernetes Service and Ingress, Vigilmon can monitor the resulting endpoint.
Example Pkl-generated Kubernetes manifest:
// k8s/deployment.pkl
import "package://pkg.pkl-lang.org/pkl-k8s/k8s@1.0.0#/K8s.pkl"
local serviceName = "user-api"
local servicePort = 8080
apiVersion = "apps/v1"
kind = "Deployment"
metadata {
name = serviceName
labels {
["app"] = serviceName
}
}
spec {
replicas = 3
selector {
matchLabels {
["app"] = serviceName
}
}
template {
spec {
containers {
new {
name = serviceName
image = "yourcompany/user-api:latest"
ports {
new { containerPort = servicePort }
}
readinessProbe {
httpGet {
path = "/healthz"
port = servicePort
}
initialDelaySeconds = 10
periodSeconds = 5
}
}
}
}
}
}
Apply the generated manifest:
pkl eval --format yaml k8s/deployment.pkl | kubectl apply -f -
Kubernetes readiness probes check the pod from inside the cluster. Vigilmon checks the ingress-exposed URL from outside — catching ingress controller failures, DNS issues, and TLS problems that in-cluster probes miss.
Step 4: Heartbeat monitoring for Pkl generation pipelines
Pkl generation is a step in your build or deployment pipeline. If it silently stops running — due to a CI configuration change, a broken Pkl import, or a schema registry outage — services stop getting updated configuration.
Use Vigilmon heartbeat monitors to verify your Pkl pipelines are running:
- In Vigilmon, go to Monitors → New Monitor
- Choose Heartbeat
- Set the expected interval to match your pipeline cadence
- Copy the heartbeat URL
Add a ping to your CI pipeline after Pkl generation:
# .github/workflows/deploy.yml
name: Deploy with Pkl
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Pkl
run: |
curl -Lo /usr/local/bin/pkl \
https://github.com/apple/pkl/releases/latest/download/pkl-linux-amd64
chmod +x /usr/local/bin/pkl
- name: Validate Pkl configs
run: pkl eval config/*.pkl --format json > /dev/null
- name: Generate Kubernetes manifests
run: pkl eval k8s/*.pkl --format yaml > manifests/
- name: Apply manifests
run: kubectl apply -f manifests/
- name: Ping Vigilmon heartbeat
run: curl -fsS --retry 3 "https://hb.vigilmon.online/your-heartbeat-id" > /dev/null
If the Pkl validation step fails (type error, constraint violation, import resolution failure), the pipeline exits before the heartbeat ping. Vigilmon alerts you within one missed interval.
Step 5: Configure alert channels
When a Pkl-configured service goes down, your team needs immediate notification — and enough context to know whether the failure is a configuration issue or an infrastructure issue.
Slack webhook integration
- In Vigilmon, go to Alert Channels → Add Channel → Webhook
- Enter your Slack incoming webhook URL
- Assign the channel to your monitors
Vigilmon's downtime payload:
{
"monitor_name": "pkl/user-api",
"status": "down",
"url": "https://api.yourcompany.com/healthz",
"started_at": "2024-01-15T10:23:00Z",
"duration_seconds": 90
}
Diagnosing Pkl-related failures when alerts fire
When Vigilmon alerts you, run this diagnostic sequence to determine whether the failure is configuration-related:
# Validate the current Pkl config
pkl eval config/production.pkl
# Check what configuration the service is actually using at runtime
curl -s https://api.yourcompany.com/debug/config | jq '.config_version'
# Compare rendered config to what's deployed
pkl eval --format json config/production.pkl > /tmp/expected.json
kubectl get configmap user-api-config -o json | jq '.data' > /tmp/actual.json
diff /tmp/expected.json /tmp/actual.json
# Check Kubernetes pod health (for k8s deployments)
kubectl get pods -l app=user-api
kubectl describe pod -l app=user-api | grep -A 5 "Conditions"
# Test the health endpoint from inside the cluster
kubectl run tmp-curl --image=curlimages/curl --rm -it --restart=Never -- \
curl http://user-api:8080/healthz
If in-cluster health checks pass but Vigilmon shows the endpoint as down, the issue is in the ingress/network path — not the configuration. If both fail, check your Pkl configuration for recent changes that could have changed service behavior.
Step 6: SSL certificate monitoring
Services configured with Pkl often specify TLS certificate settings in the Pkl config itself. Vigilmon monitors certificate expiry automatically for HTTPS monitors:
- 30 days before expiry — time to rotate
- 7 days before expiry — urgent warning
- On expiry — monitor reports down
You can encode certificate expiry alerting thresholds in your Pkl service definition:
// ServiceConfig.pkl (extended)
/// Certificate warning threshold in days
certExpiryWarnDays: Int(isBetween(7, 90)) = 30
Step 7: Status page for Pkl-managed services
Give your organization a single view of all services managed through Pkl configuration.
- In Vigilmon, go to Status Pages → New Status Page
- Name it: "Platform Services"
- Add monitors organized by domain or team:
- User Platform: user-api, auth-service
- Commerce: order-service, catalog-service
- Data: pipeline-api, analytics-service
- Publish the page
Include the status page URL in your internal developer portal so teams can check service health before filing incidents.
Putting it all together
| Monitor | Type | What it catches |
|---------|------|-----------------|
| https://api.yourcompany.com/healthz | HTTP | App failures, config errors |
| api.yourcompany.com:443 | TCP | TLS/port binding failures |
| Pkl CI pipeline heartbeat | Heartbeat | Config generation failures |
| https://api.yourcompany.com | SSL | Certificate expiry |
What's next
- Configuration-as-code for monitoring — extend your Pkl schemas to include Vigilmon monitor specifications, so adding a new service automatically generates the monitoring configuration in your CI pipeline
- Environment parity checks — monitor the same
healthPathacross production, staging, and development environments; diverging uptime between environments signals a configuration mismatch worth investigating - SLO definitions in Pkl — define availability SLO targets in your Pkl service config and cross-reference them with Vigilmon's uptime history to report on SLO compliance
Get started free at vigilmon.online — no credit card, monitors start running in under a minute.