DigitalOcean App Platform gives you a managed PaaS that handles deployments, scaling, and infrastructure. That managed experience is convenient — but it can also create a false sense of security. App Platform handles the runtime, but it doesn't tell you when your application logic is broken, when a database connection pool is exhausted, or when a third-party API your app depends on goes down.
Vigilmon fills that gap by monitoring your DigitalOcean App Platform app from the outside: polling your health endpoint every minute from external locations and alerting you within seconds of a failure. This tutorial walks you through the setup.
What You'll Build
- A
/healthendpoint in your App Platform app that reflects real dependency state - A Vigilmon HTTP monitor with regular ping checks
- Email and Slack webhook alert channels
- An SSL certificate monitor for your custom domain
Prerequisites
- A DigitalOcean account with an app deployed on App Platform
- Your app's public URL (e.g.
https://my-app.ondigitalocean.app) - A free Vigilmon account
Step 1: Add a Health Endpoint to Your App
App Platform supports any language or framework. Here are health endpoint examples for common stacks:
Node.js / Express
// server.js
app.get('/health', async (req, res) => {
const checks = {}
let ok = true
// Database check
try {
await pool.query('SELECT 1')
checks.database = 'ok'
} catch (err) {
checks.database = `error: ${err.message}`
ok = false
}
return res.status(ok ? 200 : 503).json({
status: ok ? 'ok' : 'degraded',
checks,
timestamp: new Date().toISOString(),
})
})
Python / Django
# health/views.py
from django.http import JsonResponse
from django.db import connection
from datetime import datetime
def health_check(request):
checks = {}
ok = True
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
checks["database"] = "ok"
except Exception as e:
checks["database"] = f"error: {e}"
ok = False
return JsonResponse(
{
"status": "ok" if ok else "degraded",
"checks": checks,
"timestamp": datetime.utcnow().isoformat(),
},
status=200 if ok else 503,
)
# urls.py
from health.views import health_check
urlpatterns = [
path("health/", health_check),
# ... your other routes
]
Ruby on Rails
# config/routes.rb
get '/health', to: 'health#check'
# app/controllers/health_controller.rb
class HealthController < ApplicationController
def check
checks = {}
ok = true
begin
ActiveRecord::Base.connection.execute("SELECT 1")
checks[:database] = "ok"
rescue => e
checks[:database] = "error: #{e.message}"
ok = false
end
render json: {
status: ok ? "ok" : "degraded",
checks: checks,
timestamp: Time.now.utc.iso8601
}, status: ok ? :ok : :service_unavailable
end
end
The key in all cases: return 503 when a dependency check fails. Vigilmon treats any non-2xx response as a downtime event.
Step 2: Configure App Platform Health Checks
App Platform has its own internal health check that determines whether to route traffic to your instance. Configure it in the DigitalOcean console or your app.yaml:
# .do/app.yaml
services:
- name: web
github:
repo: your-org/your-repo
branch: main
deploy_on_push: true
health_check:
http_path: /health
initial_delay_seconds: 20
period_seconds: 10
timeout_seconds: 5
success_threshold: 1
failure_threshold: 3
run_command: node server.js
instance_size_slug: basic-xxs
instance_count: 1
http_port: 8080
App Platform's internal checks prevent traffic routing to unhealthy instances. Vigilmon's external checks tell you when the entire app is down from the public internet — a failure mode App Platform's internal checks can't detect if it affects the platform itself.
Step 3: Get Your App's Public URL
After deployment, your app URL follows the pattern:
https://<your-app-name>.ondigitalocean.app
If you've added a custom domain:
https://api.yourdomain.com
Verify the health endpoint is publicly accessible:
curl -s https://my-app.ondigitalocean.app/health | jq
# {
# "status": "ok",
# "checks": { "database": "ok" },
# "timestamp": "2025-06-30T10:00:00.000Z"
# }
Step 4: Create a Vigilmon Ping Monitor
- Log in at vigilmon.online and click Add Monitor → HTTP.
- Configure the monitor:
| Field | Value |
|---|---|
| URL | https://my-app.ondigitalocean.app/health |
| Method | GET |
| Check interval | 60 seconds |
| Expected status | 200 |
| Timeout | 10 seconds |
| Regions | Select 2–3 for triangulation |
-
Under Advanced, enable a JSON body assertion:
- Path:
status - Expected value:
ok
- Path:
-
Click Save.
Vigilmon begins polling immediately. The JSON body assertion is important: it catches the case where your app returns 200 but reports "status": "degraded" — your process is alive but your database is broken.
Step 5: Add a Keyword Monitor for Your Frontend
If your App Platform app serves an HTML frontend, add a second monitor:
- Add Monitor → HTTP
- URL:
https://my-app.ondigitalocean.app/ - Expected status:
200 - Keyword check: must contain a unique string from your app (brand name, copyright text, etc.)
This catches CDN caching issues where your app's domain serves a cached error page with a 200 status — a plain HTTP check would miss it.
Step 6: SSL Certificate Monitor
App Platform manages SSL certificates automatically via Let's Encrypt, but add a Vigilmon SSL monitor as an independent safety net:
- Add Monitor → SSL Certificate
- URL:
https://my-app.ondigitalocean.app - Alert when expiry is less than: 14 days
You'll get an alert with two weeks' lead time if the certificate fails to auto-renew — enough time to investigate before users see browser TLS errors.
Step 7: Configure Alert Channels
Go to Alert Channels → Add Channel.
Add your on-call email address. Vigilmon sends:
- Down alert when the endpoint returns non-2xx or fails the JSON assertion
- Recovery alert when the endpoint comes back up
- SSL expiry warning 14 days before certificate expiry
Slack Webhook
- Create a Slack Incoming Webhook in your workspace.
- In Vigilmon: Alert Channels → Add → Webhook, paste the URL.
- Assign the channel to your monitors.
Alert format in Slack:
🔴 my-app.ondigitalocean.app/health is DOWN
Status: 503 | Duration: 1m 30s | Checked at: 2025-06-30 10:31 UTC
🟢 my-app.ondigitalocean.app/health is back UP (was down 1m 30s)
Step 8: Suppress False Alerts During Deployments
App Platform deploys trigger a rolling restart that can cause Vigilmon to detect brief downtime. Two options:
Manual maintenance window
Before triggering a deploy in the DigitalOcean console, open your Vigilmon monitor, click Maintenance Window, and set a 5-minute mute.
Automated via GitHub Actions
If you deploy via CI:
# .github/workflows/deploy.yml
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Mute Vigilmon alerts
run: |
curl -s -X POST https://vigilmon.online/api/monitors/${{ secrets.VIGILMON_MONITOR_ID }}/maintenance \
-H "Authorization: Bearer ${{ secrets.VIGILMON_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"duration_minutes": 5}'
- name: Deploy to App Platform
run: doctl apps create-deployment ${{ secrets.DO_APP_ID }}
env:
DIGITALOCEAN_ACCESS_TOKEN: ${{ secrets.DO_TOKEN }}
The maintenance window expires automatically, so monitoring resumes without manual intervention.
Production Checklist
- [ ]
/healthchecks all critical dependencies and returns503on failure - [ ] App Platform internal health check configured in
app.yaml - [ ] Vigilmon HTTP monitor with JSON body assertion
- [ ] Vigilmon keyword monitor for root URL
- [ ] Vigilmon SSL certificate monitor
- [ ] Email and Slack alert channels configured
- [ ] Alert channels tested end-to-end
- [ ] Maintenance window configured for deploy pipeline
Wrapping Up
DigitalOcean App Platform handles the infrastructure — Vigilmon handles the observability. Together they give you a complete picture: platform health inside, external uptime verification from outside.
You now have:
- External HTTP monitoring catching downtime within 60 seconds
- JSON body assertions catching degraded-but-alive states
- SSL certificate monitoring with 14-day lead time
- Deploy-safe maintenance windows for zero alert noise during releases
Sign up for Vigilmon free — 5 monitors included, no credit card required.
Running on DigitalOcean App Platform? Share your stack in the comments.