tutorial

Go Fiber Application Monitoring with Vigilmon: Uptime, Health Checks & Alerts

Monitor your Go Fiber API with Vigilmon — add a health endpoint, set up HTTP monitors, wire goroutine heartbeats, and route alerts to Slack or email.

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 /health endpoint 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

  1. Log in at vigilmon.online and click Add Monitor → HTTP.
  2. 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 |

  1. Under Alert Channels, add your email address.
  2. 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

  1. Create a Slack Incoming Webhook in your workspace.
  2. In Vigilmon: Alert Channels → Add → Webhook, paste the URL, save.
  3. 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

  • [ ] /health checks all critical dependencies (DB, Redis, upstream APIs)
  • [ ] Unhealthy checks return 503, not 200
  • [ ] Heartbeat URL stored in environment variable, not in code
  • [ ] Graceful shutdown handles SIGTERM before 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.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →