tutorial

Medusa.js Application Monitoring with Vigilmon: Health Checks, Webhooks & Alerts

Production-grade uptime monitoring for your Medusa.js e-commerce backend — add a health endpoint, set up HTTP monitors, and get alerted before your store goes dark.

Your Medusa.js store went down. Orders are failing. The checkout flow is returning 502s. Your customers are seeing blank pages and your revenue is bleeding. And you only found out because someone DM'd you on Twitter.

Medusa.js is a powerful open-source headless e-commerce platform built on Node.js. It powers storefronts, subscription flows, multi-warehouse order management, and custom checkout logic — all as composable modules. But "composable" means more moving parts, more surfaces to break, and more silent failures to miss. Vigilmon gives you the external, independent eye that watches your Medusa backend even when you're not.

This tutorial shows you how to add a health endpoint to Medusa and monitor it end-to-end with Vigilmon.

What You'll Build

  • A health check endpoint in your Medusa backend (TypeScript)
  • A Vigilmon HTTP monitor with JSON body assertion
  • A keyword monitor for your storefront API
  • Heartbeat monitoring for background workers

Prerequisites

  • A Medusa.js backend (v2.x, Node.js 20+)
  • A free account at vigilmon.online

Step 1: Add a Health Check Endpoint

Medusa v2 uses a modular architecture with Express under the hood. The cleanest way to add a health endpoint is via a custom API route.

Create the file src/api/health/route.ts:

// src/api/health/route.ts
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http";
import { ContainerRegistrationKeys } from "@medusajs/framework/utils";

export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
  const checks: Record<string, string> = {};
  let healthy = true;

  // 1. Database check via Medusa's query service
  try {
    const query = req.scope.resolve(ContainerRegistrationKeys.QUERY);
    await query.graph({ entity: "product", fields: ["id"], pagination: { take: 1 } });
    checks.database = "ok";
  } catch (e) {
    checks.database = `error: ${(e as Error).message}`;
    healthy = false;
  }

  // 2. Event bus check (Redis or in-memory)
  try {
    const eventBus = req.scope.resolve("eventBusService");
    // A noop emit — just confirms the bus is instantiated and reachable
    await eventBus.emit("health.check", {});
    checks.event_bus = "ok";
  } catch (e) {
    checks.event_bus = `error: ${(e as Error).message}`;
    // Degrade but don't mark unhealthy for event bus issues unless critical
  }

  res.status(healthy ? 200 : 503).json({
    status: healthy ? "ok" : "degraded",
    checks,
    ts: new Date().toISOString(),
  });
};

This route is automatically registered at GET /health by Medusa's file-based router.

Test it locally:

curl http://localhost:9000/health

Expected response:

{
  "status": "ok",
  "checks": {
    "database": "ok",
    "event_bus": "ok"
  },
  "ts": "2026-01-15T10:23:00.000Z"
}

If your store is already using a /health route for Kubernetes liveness probes, add a deeper /health/deep route using the same pattern for Vigilmon to hit.


Step 2: Monitor the Health Endpoint with Vigilmon

  1. Log in to Vigilmon and click New Monitor → HTTP.
  2. Set URL to https://api.your-store.com/health.
  3. Set Check interval to 60 seconds.
  4. Set Expected status code to 200.
  5. Under Advanced → JSON body assertion, add:
    • Path: status
    • Expected value: ok
  6. Save the monitor.

Vigilmon now polls your health endpoint from multiple external regions every minute. If the database connection pool drains, the event bus crashes, or the server stops responding entirely, you'll receive an alert within 60 seconds.


Step 3: Monitor the Storefront API

Medusa exposes its Store API at /store. A broken auth middleware or a corrupted product module can cause 5xx errors that your health endpoint never sees. Add a second monitor targeting a lightweight Store API call.

  1. Click New Monitor → HTTP.
  2. Set URL to https://api.your-store.com/store/products?limit=1.
  3. Set Expected status code to 200.
  4. Under Advanced → Keyword check, set:
    • Keyword present: "products"
    • Keyword absent: "error"
  5. Save.

This catches broken product routes, corrupted module state, and middleware regressions that a database ping won't surface.


Step 4: Alert Channels

Go to Notifications → New Channel in Vigilmon and add:

  • Email — immediate alert to your engineering on-call inbox
  • Webhook — forward to Slack, PagerDuty, or Discord

For Slack, create an incoming webhook at api.slack.com/apps and paste it into Vigilmon. A down alert looks like:

🔴 DOWN: api.your-store.com/health
Status: 503 Service Unavailable
Region: US-East
3 minutes ago

When the backend recovers:

✅ RECOVERED: api.your-store.com/health
Downtime: 4 minutes

Step 5: Heartbeat Monitor for Background Workers

Medusa's subscriber/workflow system runs background jobs — order processing, inventory sync, email triggers. HTTP monitors can't see these. Use Vigilmon's heartbeat pattern instead.

In any Medusa subscriber or workflow step, ping Vigilmon at the end of each successful run:

// src/subscribers/inventory-sync.ts
import type { SubscriberArgs } from "@medusajs/framework";

export default async function inventorySyncHandler({ event }: SubscriberArgs) {
  try {
    await runInventorySync();

    // Ping Vigilmon heartbeat on success
    const heartbeatUrl = process.env.VIGILMON_HEARTBEAT_URL;
    if (heartbeatUrl) {
      await fetch(heartbeatUrl, { method: "POST" });
    }
  } catch (error) {
    // No ping on failure — Vigilmon will alert on missed ping
    throw error;
  }
}

async function runInventorySync() {
  // your inventory sync logic
}

export const config = {
  event: "product.updated",
};

Set the environment variable:

VIGILMON_HEARTBEAT_URL=https://vigilmon.online/api/heartbeat/<your-id>

In Vigilmon, create a Heartbeat Monitor with a grace period slightly longer than your job interval. If the job stops firing — due to a crash, a dead Redis queue, or a misconfigured subscriber — Vigilmon alerts before your inventory drifts.


Step 6: Status Page

Go to Status Pages → New Status Page in Vigilmon. Add both monitors (health endpoint and Store API) and share the public URL. Add the badge to your storefront README:

![API Status](https://vigilmon.online/badge/<monitor-slug>)

What You've Built

| Scenario | How Vigilmon catches it | |---|---| | Database connection pool exhausted | Health endpoint returns degraded, alert fires | | Event bus (Redis) goes down | Health endpoint reports event_bus error | | Broken product module / middleware regression | Store API keyword monitor fails | | Background inventory sync stops | Heartbeat monitor misses ping, alert fires | | Entire backend unreachable (crash, OOM, deploy failure) | HTTP timeout on health endpoint | | Checkout API silent 5xx | Additional monitor on /store/carts endpoint |


Medusa's power comes from its composability — but each module is a potential failure point. Vigilmon gives you the external, independent view that catches what your internal health checks miss.

Start monitoring your Medusa.js store today — register free at vigilmon.online.

Monitor your app with Vigilmon

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

Start free →