Rust web services built with Actix-web are known for their exceptional performance and memory safety. But even a correctly written Rust service can go down due to infrastructure issues, configuration errors, or upstream dependency failures. External uptime monitoring is the safety net that catches these failures before your users do.
This guide shows you how to add a health check endpoint to an Actix-web service and monitor it with Vigilmon.
Why Rust Services Need Uptime Monitoring
Rust's type system eliminates entire classes of bugs, but it doesn't prevent:
- Process crashes: Panics, OOM kills, or infrastructure-level crashes
- Network failures: Load balancer misconfiguration, firewall changes
- Dependency failures: PostgreSQL, Redis, or external APIs going down
- Deployment rollout issues: New binary crashes on startup due to env var mismatches
Vigilmon monitors from outside your infrastructure, giving you an independent view of availability.
Step 1: Add a Health Check Endpoint
Basic Health Check
Add a /health route to your Actix-web app:
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use serde_json::json;
#[get("/health")]
async fn health() -> impl Responder {
HttpResponse::Ok().json(json!({
"status": "ok",
"service": "my-api",
}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(health)
// ... your other routes
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
Health Check with Database Verification
For services backed by PostgreSQL (via sqlx):
use actix_web::{get, web, HttpResponse, Responder};
use sqlx::PgPool;
use serde_json::json;
#[get("/health")]
async fn health(pool: web::Data<PgPool>) -> impl Responder {
match sqlx::query("SELECT 1")
.execute(pool.get_ref())
.await
{
Ok(_) => HttpResponse::Ok().json(json!({
"status": "ok",
"db": "connected"
})),
Err(e) => HttpResponse::ServiceUnavailable().json(json!({
"status": "error",
"db": e.to_string()
})),
}
}
Register the pool in your app state:
#[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");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.service(health)
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
Health Check with Redis (deadpool-redis)
use deadpool_redis::{Config, Pool, Runtime};
use actix_web::{get, web, HttpResponse, Responder};
#[get("/health")]
async fn health(pool: web::Data<Pool>) -> impl Responder {
let mut conn = match pool.get().await {
Ok(c) => c,
Err(e) => {
return HttpResponse::ServiceUnavailable().json(
serde_json::json!({"status": "error", "redis": e.to_string()})
);
}
};
match deadpool_redis::redis::cmd("PING")
.query_async::<String>(&mut conn)
.await
{
Ok(_) => HttpResponse::Ok().json(serde_json::json!({"status": "ok", "redis": "connected"})),
Err(e) => HttpResponse::ServiceUnavailable().json(
serde_json::json!({"status": "error", "redis": e.to_string()})
),
}
}
Step 2: Build and Test
cargo build --release
./target/release/your-service &
# Test the health endpoint
curl http://localhost:8080/health
# {"status":"ok","db":"connected"}
Step 3: Configure Vigilmon
- Go to vigilmon.online and sign up
- Click New Monitor
- Set:
-
URL:
https://api.yourservice.com/health - Type: HTTP
- Interval: 60 seconds
- Expected status: 200
-
URL:
- Add alert channels
- Save
Vigilmon will alert you within 60 seconds of any failure.
Deployment Patterns
Docker
FROM rust:1.79-slim AS builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
COPY --from=builder /app/target/release/your-service /usr/local/bin/
EXPOSE 8080
CMD ["your-service"]
Add a Docker health check:
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
Docker's health check restarts the container if it fails. Vigilmon tells your team.
systemd Service
[Unit]
Description=Actix-web API Service
After=network.target
[Service]
ExecStart=/usr/local/bin/your-service
Restart=always
RestartSec=5
EnvironmentFile=/etc/your-service/env
[Install]
WantedBy=multi-user.target
Kubernetes
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
K8s probes handle internal restarts; Vigilmon provides external visibility and user-facing alerting.
Response Time Monitoring
Rust/Actix-web services are typically fast (<10ms for simple endpoints). If your /health response time exceeds 100ms, something is wrong. Set a Vigilmon response time alert:
- Alert threshold: 500ms
- Action: Slack notification + email
Summary
Your Actix-web service is fast, but it's not immortal. Set up external monitoring in 3 steps:
- Add a
/healthendpoint that checks your dependencies - Configure Vigilmon to poll it every 60 seconds
- Set up Slack/email alerts for immediate notification
Top comments (0)