tutorial

Monitoring Prisma ORM Database Infrastructure with Vigilmon

Prisma ORM connects your app to your database — but database connectivity failures, slow queries, and migration drift happen silently. Here's how to monitor your Prisma-backed database infrastructure with Vigilmon.

Prisma is the most popular ORM for Node.js and TypeScript, used with PostgreSQL, MySQL, SQLite, and MongoDB. Your app code trusts Prisma to bridge the gap to the database — but when the database goes down, the connection pool exhausts, or a migration leaves the schema out of sync, your API starts throwing errors with no proactive alert. Vigilmon gives you uptime checks, database health probes, and alerting to catch infrastructure failures before they cascade into user-facing downtime.

What You'll Set Up

  • HTTP health endpoint that verifies Prisma database connectivity
  • Uptime monitor for API servers using Prisma
  • TCP port monitor for the database server
  • Cron heartbeat for Prisma-powered background workers
  • SSL monitoring for database admin interfaces

Prerequisites

  • Prisma Client installed and configured (@prisma/client)
  • A backend API (Express, Fastify, NestJS, or similar) using Prisma
  • A free Vigilmon account

Step 1: Add a Database Health Check Endpoint

The most important thing to monitor with Prisma is actual database connectivity. A /health endpoint that calls Prisma's $queryRaw lets Vigilmon verify the full connection path — connection pool, credentials, and network — on every probe:

Express

import express from 'express';
import { PrismaClient } from '@prisma/client';

const app = express();
const prisma = new PrismaClient();

app.get('/health', async (req, res) => {
  try {
    // Lightweight DB ping — uses an existing connection from the pool
    await prisma.$queryRaw`SELECT 1`;
    res.json({
      status: 'ok',
      database: 'connected',
      uptime: process.uptime(),
    });
  } catch (err) {
    res.status(503).json({
      status: 'error',
      database: 'unreachable',
      detail: err.message,
    });
  }
});

app.listen(3000);

Fastify

import Fastify from 'fastify';
import { PrismaClient } from '@prisma/client';

const app = Fastify();
const prisma = new PrismaClient();

app.get('/health', async (request, reply) => {
  try {
    await prisma.$queryRaw`SELECT 1`;
    return { status: 'ok', database: 'connected' };
  } catch (err) {
    return reply.status(503).send({ status: 'error', detail: err.message });
  }
});

app.listen({ port: 3000 });

NestJS

// health.controller.ts
import { Controller, Get } from '@nestjs/common';
import { PrismaService } from './prisma.service';

@Controller()
export class HealthController {
  constructor(private prisma: PrismaService) {}

  @Get('health')
  async health() {
    try {
      await this.prisma.$queryRaw`SELECT 1`;
      return { status: 'ok', database: 'connected' };
    } catch (err) {
      throw new ServiceUnavailableException({ status: 'error', detail: err.message });
    }
  }
}

SELECT 1 is the lightest possible query — it does not touch any table or trigger any application logic, but it does traverse the full Prisma → connection pool → database path.


Step 2: Add Connection Pool Metrics to the Health Check

Prisma's connection pool can silently exhaust under load, causing new requests to hang. Add pool metrics to your health endpoint to detect exhaustion before it causes downtime:

app.get('/health', async (req, res) => {
  try {
    await prisma.$queryRaw`SELECT 1`;

    // $metrics is available in Prisma 4+ with the metrics preview feature
    // Enable in schema.prisma: previewFeatures = ["metrics"]
    const metrics = await prisma.$metrics.json();
    const poolWaiting = metrics.counters.find(
      c => c.key === 'prisma_pool_connections_idle'
    );

    res.json({
      status: 'ok',
      database: 'connected',
      pool: poolWaiting?.value ?? 'unknown',
      uptime: process.uptime(),
    });
  } catch (err) {
    res.status(503).json({ status: 'error', detail: err.message });
  }
});

Enable Prisma metrics in schema.prisma:

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["metrics"]
}

Step 3: Add Vigilmon Monitors

Monitor 1: API Health Endpoint

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter: https://api.yourdomain.com/health
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Optionally set Response must contain to "database":"connected".
  7. Click Save.

The response body check ensures the monitor distinguishes a running-but-database-disconnected server from a fully healthy one.

Monitor 2: TCP Port for the Database Server

Even if your API's health endpoint fails, knowing whether the database port is reachable narrows the diagnosis. Add a TCP monitor directly to the database host:

  1. Click Add MonitorTCP Port.
  2. Set Host to your database server IP (e.g. db.internal.yourdomain.com or a private IP).
  3. Set Port to:
    • PostgreSQL: 5432
    • MySQL / PlanetScale: 3306
    • MongoDB: 27017
  4. Set Check interval to 1 minute.
  5. Click Save.

If the TCP monitor fails but the API health endpoint is up, the database connection pool is caching stale connections — a Prisma restart will fix it. If both fail, the database host is unreachable.


Step 4: Heartbeat for Prisma-Based Background Workers

Many Prisma apps run background jobs that write to the database — queue processors, scheduled tasks, data sync workers. Use a Vigilmon heartbeat to confirm these workers are alive:

  1. In Vigilmon, click Add MonitorCron Heartbeat.
  2. Set the expected ping interval to match your job frequency.
  3. Copy the heartbeat URL.
  4. Add the heartbeat call at the end of each successful job run:
import fetch from 'node-fetch';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();
const HEARTBEAT_URL = 'https://vigilmon.online/heartbeat/YOUR_KEY';

async function processJob() {
  // ... read from DB, process, write results
  const items = await prisma.job.findMany({ where: { status: 'pending' } });
  for (const item of items) {
    await processItem(item);
    await prisma.job.update({ where: { id: item.id }, data: { status: 'done' } });
  }

  // Signal Vigilmon that the job completed successfully
  await fetch(HEARTBEAT_URL).catch(() => {});
}

If the job throws (e.g. due to a database constraint violation), it never pings, and Vigilmon alerts after the expected interval.


Step 5: Monitor Database Admin Interfaces

If you run Prisma Studio, pgAdmin, or Adminer for database management, add uptime monitors for those interfaces:

# Prisma Studio (default port)
http://localhost:5555

# pgAdmin
https://admin.yourdomain.com

# Adminer
https://db-admin.yourdomain.com

For publicly accessible admin interfaces, also enable SSL monitoring:

  1. Open the monitor for the admin interface.
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

Step 6: Migration Drift Detection

Prisma migrations can drift in production if a migration is applied partially or if schema changes are made directly to the database. Add a heartbeat for your CI/CD migration step so you know migrations ran:

# Example: GitHub Actions migration step with Vigilmon heartbeat
- name: Run Prisma migrations
  run: |
    npx prisma migrate deploy
    curl -s https://vigilmon.online/heartbeat/MIGRATION_KEY
  env:
    DATABASE_URL: ${{ secrets.DATABASE_URL }}

If prisma migrate deploy fails, the curl is never reached, and the heartbeat misses its expected ping.


Step 7: Alert Configuration

  1. Go to Alert Channels in Vigilmon and add Slack, email, or PagerDuty.
  2. Set Consecutive failures before alert to 2 on the API health monitor — a single probe can catch a transient connection error.
  3. Set Consecutive failures before alert to 1 on the TCP database monitor — database port closure is never transient.
  4. Suppress alerts during maintenance windows or migrations:
curl -X POST https://vigilmon.online/api/maintenance \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"monitor_id": "YOUR_MONITOR_ID", "duration_minutes": 10}'

npx prisma migrate deploy

Summary

| Monitor | Target | What It Catches | |---|---|---| | API health endpoint | /health with SELECT 1 | Database connectivity failure | | TCP port | DB host :5432 / :3306 | Database server down | | SSL certificate | API / admin domain | TLS cert expiry | | Cron heartbeat | Background worker | Job crash, missed schedule | | CI heartbeat | Migration step | Failed or skipped migration |

Prisma is a powerful abstraction — but abstractions don't monitor themselves. With a SELECT 1 health probe, a direct TCP check on the database port, and heartbeats on your background workers, you have full visibility into your Prisma-backed infrastructure from the ORM layer down to the database server.

Monitor your app with Vigilmon

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

Start free →