How to Monitor AWS RDS and Aurora with Vigilmon
AWS RDS and Aurora provide managed database infrastructure, but "managed" doesn't mean "always up." Databases go into maintenance windows, connection pools exhaust, and replica lag grows. This guide shows how to build application-level database monitoring that surfaces problems before users hit errors.
What to Monitor
RDS/Aurora health has two layers:
- AWS-level: instance status, CPU, storage-visible in CloudWatch
- Application-level: can your app actually query the database?-visible via your health endpoint
Vigilmon monitors layer 2. CloudWatch handles layer 1. You need both.
Adding a Database Health Endpoint
Node.js with pg (PostgreSQL/Aurora Postgres)
` ypescript
import express from "express";
import { Pool } from "pg";
const pool = new Pool({
host: process.env.RDS_HOSTNAME,
port: parseInt(process.env.RDS_PORT || "5432"),
database: process.env.RDS_DB_NAME,
user: process.env.RDS_USERNAME,
password: process.env.RDS_PASSWORD,
ssl: { rejectUnauthorized: false }, // Required for RDS SSL
connectionTimeoutMillis: 5000,
idleTimeoutMillis: 30000,
max: 20,
});
const app = express();
app.get("/health", async (req, res) => {
const start = Date.now();
try {
const result = await pool.query("SELECT 1 as ok, NOW() as ts");
const latency = Date.now() - start;
res.json({
status: "ok",
database: {
connected: true,
latencyMs: latency,
timestamp: result.rows[0].ts,
},
});
} catch (error) {
console.error("DB health check failed:", error);
res.status(503).json({
status: "error",
database: {
connected: false,
error: error instanceof Error ? error.message : "Unknown error",
},
});
}
});
app.listen(3000);
`
Python with SQLAlchemy (Aurora MySQL/Postgres)
`python
from flask import Flask, jsonify
from sqlalchemy import create_engine, text
from sqlalchemy.exc import OperationalError
import os
import time
app = Flask(name)
engine = create_engine(
f"postgresql://{os.environ['DB_USER']}:{os.environ['DB_PASSWORD']}"
f"@{os.environ['DB_HOST']}:{os.environ.get('DB_PORT', '5432')}/{os.environ['DB_NAME']}",
pool_pre_ping=True, # Test connection before use
pool_size=5,
max_overflow=10,
connect_args={
"connect_timeout": 5,
"sslmode": "require" # Required for RDS
}
)
@app.route("/health")
def health():
start = time.time()
try:
with engine.connect() as conn:
result = conn.execute(text("SELECT 1"))
latency_ms = int((time.time() - start) * 1000)
return jsonify({
"status": "ok",
"database": {
"connected": True,
"latencyMs": latency_ms
}
}), 200
except OperationalError as e:
return jsonify({
"status": "error",
"database": {
"connected": False,
"error": str(e)
}
}), 503
if name == "main":
app.run(port=5000)
`
Go with database/sql
`go
package main
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
_ "github.com/lib/pq"
)
var db *sql.DB
func healthHandler(w http.ResponseWriter, r *http.Request) {
start := time.Now()
err := db.PingContext(r.Context())
latency := time.Since(start).Milliseconds()
w.Header().Set("Content-Type", "application/json")
if err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "error",
"database": map[string]interface{}{
"connected": false,
"error": err.Error(),
},
})
return
}
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "ok",
"database": map[string]interface{}{
"connected": true,
"latencyMs": latency,
},
})
}
func main() {
connStr := fmt.Sprintf(
"host=%s port=%s user=%s password=%s dbname=%s sslmode=require",
os.Getenv("DB_HOST"),
os.Getenv("DB_PORT"),
os.Getenv("DB_USER"),
os.Getenv("DB_PASSWORD"),
os.Getenv("DB_NAME"),
)
var err error
db, err = sql.Open("postgres", connStr)
if err != nil {
panic(err)
}
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
http.HandleFunc("/health", healthHandler)
http.ListenAndServe(":8080", nil)
}
`
Aurora-Specific: Read Replica Monitoring
Aurora provides a reader endpoint for read replicas. Monitor it separately:
` ypescript
// Monitor writer endpoint
const writerPool = new Pool({ host: process.env.AURORA_WRITER_ENDPOINT, ... });
// Monitor reader endpoint
const readerPool = new Pool({ host: process.env.AURORA_READER_ENDPOINT, ... });
app.get("/health", async (req, res) => {
const [writerOk, readerOk] = await Promise.allSettled([
writerPool.query("SELECT 1"),
readerPool.query("SELECT 1"),
]);
const status = writerOk.status === "fulfilled" ? "ok" : "error";
res.status(status === "ok" ? 200 : 503).json({
status,
writer: writerOk.status === "fulfilled" ? "ok" : "error",
reader: readerOk.status === "fulfilled" ? "ok" : "degraded",
});
});
`
In Vigilmon, add two monitors:
- https://yourapp.com/health - main health check
- https://yourapp.com/health/db-writer - writer-specific
- https://yourapp.com/health/db-reader - reader-specific
Handling RDS Maintenance Windows
During RDS maintenance, connections drop briefly. Your health endpoint may return 503. Configure Vigilmon to require 2 consecutive failures before alerting to avoid false alarms:
In Vigilmon ? Monitor settings ? Failure threshold: 2
This means one failed check won't page you, but two in a row will.
Setting Up Vigilmon
- Go to vigilmon.online
- Add monitors for:
- Your app's /health endpoint (HTTP check)
- Your RDS domain (TCP check on port 5432/3306)
- Your SSL certificate
TCP Monitor for RDS Direct
If you want to monitor the RDS endpoint directly:
- Type: TCP
- Host: your-instance.xxxx.us-east-1.rds.amazonaws.com
- Port: 5432 (PostgreSQL) or 3306 (MySQL)
- Interval: 5 minutes
Note: Ensure your Vigilmon probe IPs are allowed in your RDS security group, or use application-level health endpoints instead.
Recommended Alert Setup
| Event | Alert |
|---|---|
| Health endpoint 503 | Slack + PagerDuty (immediate) |
| Response time >2s | Slack (warning) |
| SSL expiry <30d | |
| 2+ consecutive failures | PagerDuty (wake-up) |
Summary
- Add a /health endpoint that actively queries RDS/Aurora
- Return 503 when the database is unreachable
- Monitor writer and reader endpoints separately for Aurora
- Set failure threshold to 2 to avoid maintenance window false alarms
- Use Vigilmon for external checks + CloudWatch for AWS-level metrics
Set up RDS monitoring at vigilmon.online - free plan includes 3 monitors.
Top comments (0)