How to Monitor Your Rust (Actix-web) Application with Vigilmon
Rust applications built with Actix-web are known for exceptional performance and reliability — but even zero-cost abstractions can't protect you from network outages, DNS failures, or upstream service disruptions. External uptime monitoring fills that gap.
This guide shows how to add health checks to your Actix-web app and connect them to Vigilmon for 24/7 external uptime monitoring with instant alerts.
Why External Monitoring for Rust/Actix-web?
Actix-web is blazing fast and memory-safe, but your app still depends on:
- Network connectivity and DNS resolution
- Downstream services (PostgreSQL, Redis, external APIs)
- Docker/systemd process management
- Cloud infrastructure (load balancers, ingress controllers)
Internal logging and metrics won't tell you when the entire process crashes or the network drops. External monitoring pings your app from outside and alerts you within seconds.
Step 1: Add a Health Check Endpoint
Add a /health route that checks your critical dependencies:
use actix_web::{web, App, HttpServer, HttpResponse, middleware};
use sqlx::PgPool;
async fn health_check(pool: web::Data<PgPool>) -> HttpResponse {
// Check database connectivity
match sqlx::query("SELECT 1")
.fetch_one(pool.get_ref())
.await
{
Ok(_) => HttpResponse::Ok().json(serde_json::json!({
"status": "healthy",
"database": "connected",
"version": env!("CARGO_PKG_VERSION")
})),
Err(e) => HttpResponse::ServiceUnavailable().json(serde_json::json!({
"status": "unhealthy",
"database": "disconnected",
"error": e.to_string()
}))
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let pool = PgPool::connect(&std::env::var("DATABASE_URL").unwrap())
.await
.expect("Failed to connect to database");
let pool_data = web::Data::new(pool);
HttpServer::new(move || {
App::new()
.app_data(pool_data.clone())
.route("/health", web::get().to(health_check))
// ... your other routes
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
Step 2: Lightweight Liveness vs Readiness Checks
Follow the Kubernetes pattern — separate checks for different purposes:
// Liveness: Is the process alive? (no dependencies)
async fn liveness() -> HttpResponse {
HttpResponse::Ok().json(serde_json::json!({"status": "alive"}))
}
// Readiness: Can we serve traffic? (check dependencies)
async fn readiness(
pool: web::Data<PgPool>,
redis: web::Data<redis::Client>,
) -> HttpResponse {
let db_ok = sqlx::query("SELECT 1")
.fetch_one(pool.get_ref())
.await
.is_ok();
let redis_ok = redis
.get_async_connection()
.await
.map(|_| true)
.unwrap_or(false);
if db_ok && redis_ok {
HttpResponse::Ok().json(serde_json::json!({
"status": "ready",
"database": true,
"cache": true
}))
} else {
HttpResponse::ServiceUnavailable().json(serde_json::json!({
"status": "not_ready",
"database": db_ok,
"cache": redis_ok
}))
}
}
Register both in your Actix app:
App::new()
.route("/health/live", web::get().to(liveness))
.route("/health/ready", web::get().to(readiness))
Step 3: Connect Vigilmon
- Sign up at vigilmon.online
- Create a new monitor → HTTP Monitor
- Set the URL to
https://yourdomain.com/health - Check interval: 1 minute (recommended)
- Configure alerts: email, Slack, PagerDuty, or webhook
- Save and watch your first ping succeed
Vigilmon sends an HTTP GET to your endpoint every minute from multiple regions. If it gets a non-2xx response or no response within the timeout, you're alerted immediately.
Step 4: Actix-web Middleware for Request Timing
Add structured logging with response times so you can correlate Vigilmon alerts with your own logs:
use actix_web::middleware::Logger;
use env_logger::Env;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(Env::default().default_filter_or("info"));
HttpServer::new(|| {
App::new()
.wrap(Logger::new("%a %r %s %b %T")) // includes response time
.route("/health", web::get().to(health_check))
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
When Vigilmon triggers an alert, you can immediately grep your logs for the timestamp to see what happened.
Step 5: Docker Health Checks
If you're running in Docker, add a native health check to your Dockerfile:
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/myapp /usr/local/bin/myapp
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \n CMD curl -f http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["myapp"]
Docker's built-in health check restarts unhealthy containers. Vigilmon's external monitoring alerts you when the entire host or network is unreachable — something Docker can't detect from inside.
What Vigilmon Monitors That You Can't See Internally
| Failure Mode | Internal Logs | Vigilmon |
|---|---|---|
| Process crash | Silent | ✅ Alert within 1 min |
| DNS failure | Silent | ✅ Alert within 1 min |
| Network partition | Silent | ✅ Alert within 1 min |
| SSL certificate expiry | Manual check | ✅ 30/14/7 day warnings |
| Slow responses (> 5s) | Visible | ✅ Alert + timing history |
| Database connection pool exhaustion | Sometimes | ✅ Via health endpoint |
Free Tier
Vigilmon's free tier includes:
- 5 monitors
- 1-minute check intervals
- Email alerts
- 90-day uptime history
Perfect for side projects and startups. No credit card required.
Summary
- Add
/health(and optionally/health/live+/health/ready) to your Actix-web app - Return
200 OKwhen healthy,503when degraded - Connect Vigilmon and set your alert channels
- Sleep soundly knowing you'll be the first to know about downtime
Rust gives you memory safety and performance. Vigilmon gives you visibility. Together, your production app is both fast and observable.
Start monitoring free at vigilmon.online — no credit card required.
Top comments (0)