Go Fiber is an Express-inspired web framework built on top of FastHTTP, making it one of the fastest Go HTTP frameworks available. Its low-overhead routing and Express-style middleware API make it popular for high-performance APIs and microservices. But "high performance" and "high availability" are different things — your Fiber app can be blazing fast and still go offline due to a misconfigured deployment, a database connection leak, or a silent goroutine panic.
Vigilmon gives you an independent external view of your API's health, polling it every minute from multiple regions and alerting you within seconds of a failure. This tutorial wires your Go Fiber application into Vigilmon for uptime monitoring, health checks, and alert routing.
Note: If you're using Gin rather than Fiber, see the Go Gin monitoring tutorial — the setup is similar but uses Gin's context API.
What You'll Build
- A
/healthendpoint in Fiber with database and dependency checks - A Vigilmon HTTP monitor with multi-region polling
- A goroutine heartbeat for background worker monitoring
- Email and Slack webhook alert channels
Prerequisites
- Go 1.21+
- A Go Fiber project (
go get github.com/gofiber/fiber/v2) or existing app - A free Vigilmon account
Step 1: Add a Health Endpoint
Create a dedicated health handler that checks your actual dependencies, not just whether the process is alive.
// internal/health/handler.go
package health
import (
"database/sql"
"time"
"github.com/gofiber/fiber/v2"
)
type Handler struct {
DB *sql.DB
}
type HealthResponse struct {
Status string `json:"status"`
Checks map[string]string `json:"checks"`
Timestamp time.Time `json:"timestamp"`
}
func (h *Handler) Check(c *fiber.Ctx) error {
checks := map[string]string{}
overallStatus := "ok"
httpStatus := fiber.StatusOK
// Database ping with a 2-second deadline
ctx := c.Context()
if err := h.DB.PingContext(ctx); err != nil {
checks["database"] = "error: " + err.Error()
overallStatus = "degraded"
httpStatus = fiber.StatusServiceUnavailable
} else {
checks["database"] = "ok"
}
return c.Status(httpStatus).JSON(HealthResponse{
Status: overallStatus,
Checks: checks,
Timestamp: time.Now().UTC(),
})
}
Register the route in your main setup:
// main.go (excerpt)
import (
"github.com/gofiber/fiber/v2"
"yourmodule/internal/health"
)
app := fiber.New()
healthHandler := &health.Handler{DB: db}
app.Get("/health", healthHandler.Check)
// Your other routes...
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello from Fiber!")
})
Test locally:
curl -s localhost:3000/health | jq
# {
# "status": "ok",
# "checks": { "database": "ok" },
# "timestamp": "2025-06-30T10:00:00Z"
# }
When your database is unreachable, the endpoint returns 503. Vigilmon treats any non-2xx response as a downtime event and fires the alert chain immediately.
Step 2: Add a Cache Check
If your app uses Redis or Memcached, add it to the health payload:
import (
"context"
"github.com/redis/go-redis/v9"
)
type Handler struct {
DB *sql.DB
Redis *redis.Client
}
func (h *Handler) Check(c *fiber.Ctx) error {
checks := map[string]string{}
ok := true
// Database
if err := h.DB.PingContext(c.Context()); err != nil {
checks["database"] = "error: " + err.Error()
ok = false
} else {
checks["database"] = "ok"
}
// Redis
if h.Redis != nil {
if err := h.Redis.Ping(context.Background()).Err(); err != nil {
checks["redis"] = "error: " + err.Error()
ok = false
} else {
checks["redis"] = "ok"
}
}
status := "ok"
httpStatus := fiber.StatusOK
if !ok {
status = "degraded"
httpStatus = fiber.StatusServiceUnavailable
}
return c.Status(httpStatus).JSON(fiber.Map{
"status": status,
"checks": checks,
"timestamp": time.Now().UTC(),
})
}
Step 3: Create a Vigilmon HTTP Monitor
- Log in at vigilmon.online and click Add Monitor → HTTP.
- Configure the monitor:
| Field | Value |
|---|---|
| URL | https://api.yourdomain.com/health |
| Method | GET |
| Check interval | 60 seconds |
| Expected status | 200 |
| Timeout | 10 seconds |
| Regions | Select 2–3 for triangulation |
- Under Alert Channels, add your email address.
- Click Save — Vigilmon begins polling immediately.
Pro tip: If your Fiber API requires authentication, add an Authorization header in the monitor's Advanced → Request Headers section. Use a dedicated read-only health token, never a user credential.
Step 4: Goroutine Heartbeat for Background Workers
HTTP uptime checks confirm your API is responding, but they don't tell you whether your background workers are alive. The heartbeat pattern fills that gap: your worker pings Vigilmon on each successful cycle. If pings stop, Vigilmon alerts you.
Get your Heartbeat URL from Vigilmon: Dashboard → Heartbeat Monitors → New.
// internal/worker/heartbeat.go
package worker
import (
"context"
"log"
"net/http"
"time"
)
const heartbeatInterval = 60 * time.Second
func RunWithHeartbeat(ctx context.Context, heartbeatURL string, work func(context.Context) error) {
ticker := time.NewTicker(heartbeatInterval)
defer ticker.Stop()
client := &http.Client{Timeout: 5 * time.Second}
ping := func() {
resp, err := client.Get(heartbeatURL)
if err != nil {
log.Printf("[heartbeat] ping failed: %v", err)
return
}
resp.Body.Close()
}
ping() // Ping immediately on startup
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
if err := work(ctx); err != nil {
log.Printf("[worker] error: %v — skipping heartbeat", err)
continue // Don't ping on failure; let Vigilmon detect the silence
}
ping()
}
}
}
Start the worker from main:
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go worker.RunWithHeartbeat(ctx, os.Getenv("VIGILMON_HEARTBEAT_URL"), processQueue)
Store the URL in your environment:
VIGILMON_HEARTBEAT_URL=https://vigilmon.online/api/heartbeats/YOUR-UUID/ping
Step 5: Graceful Shutdown
Fiber provides a ShutdownWithContext method. Pair it with OS signal handling to avoid false alerts during deployments:
// main.go
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New(fiber.Config{
// Disable Fiber's default startup banner to keep logs clean
DisableStartupMessage: false,
})
// ... register routes ...
// Start in background
go func() {
if err := app.Listen(":3000"); err != nil {
log.Printf("server error: %v", err)
}
}()
// Block until signal
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("shutting down...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := app.ShutdownWithContext(ctx); err != nil {
log.Fatalf("forced shutdown: %v", err)
}
log.Println("server exited cleanly")
}
During planned maintenance, use Vigilmon's Maintenance Windows feature to mute alerts for the duration of your deploy.
Step 6: Configure Alert Channels
Slack Webhook
- Create a Slack Incoming Webhook in your workspace.
- In Vigilmon: Alert Channels → Add → Webhook, paste the URL, save.
- Assign the webhook to your monitors.
Alert payloads look like:
🔴 api.yourdomain.com/health is DOWN
Status: 503 | Region: us-east-1 | Duration: 1m 45s
🟢 api.yourdomain.com/health is back UP (was down 1m 45s)
PagerDuty / Teams
Vigilmon also supports PagerDuty integration and Microsoft Teams webhooks — useful for on-call rotation and enterprise alert routing.
Production Checklist
- [ ]
/healthchecks all critical dependencies (DB, Redis, upstream APIs) - [ ] Unhealthy checks return
503, not200 - [ ] Heartbeat URL stored in environment variable, not in code
- [ ] Graceful shutdown handles
SIGTERMbefore in-flight requests complete - [ ] Alert channels tested before your first production incident
- [ ] Maintenance windows configured for your deploy pipeline
Wrapping Up
You now have production-grade monitoring for your Go Fiber API:
- HTTP uptime monitoring catching failures within 60 seconds
- Goroutine heartbeat monitoring catching silent worker failures
- Alert routing to Slack and email with recovery notifications
Sign up for Vigilmon free — no credit card required, first 5 monitors included.
Using Fiber in production? Share your stack in the comments.