tRPC is the type-safe RPC framework that's taken the TypeScript ecosystem by storm — especially in Next.js and T3 Stack applications. But monitoring a tRPC API has some quirks compared to REST APIs. Here's how to set up proper monitoring.
The tRPC Monitoring Challenge
Standard HTTP monitoring works by hitting a URL and checking the response. tRPC complicates this because:
-
All procedures go through a single endpoint (typically
/api/trpc/[trpc]) - Queries use GET, mutations use POST — but the path is the procedure name
- There's no standard health check endpoint out of the box
You can't just monitor /api/trpc — it'll return 404 or an error since you haven't specified a procedure.
Solution 1: Add a Dedicated Health Check Procedure
The cleanest solution is adding a healthCheck query to your tRPC router:
// server/api/routers/health.ts
import { createTRPCRouter, publicProcedure } from '~/server/api/trpc'
export const healthRouter = createTRPCRouter({
check: publicProcedure.query(async () => {
return {
status: 'ok',
timestamp: new Date().toISOString(),
}
}),
})
Merge it into your root router:
// server/api/root.ts
import { healthRouter } from './routers/health'
export const appRouter = createTRPCRouter({
health: healthRouter,
// ...your other routers
})
Now you can monitor this procedure at:
GET https://your-app.com/api/trpc/health.check
Vigilmon will hit this URL, expect a 200 response with JSON containing "status":"ok", and alert you if anything goes wrong.
Setting Up the Vigilmon Monitor
- Go to vigilmon.online and create a free account
- Click Add Monitor → HTTP Monitor
- Enter the URL:
https://your-app.com/api/trpc/health.check - Set the expected status code to 200
- Add a keyword check:
"status":"ok" - Set interval to 60 seconds
- Enable multi-region to avoid false positives
Solution 2: Add a Standalone Health Route (Next.js)
If you're using Next.js, you can also add a dedicated health route that doesn't go through tRPC:
// app/api/health/route.ts (Next.js App Router)
import { NextResponse } from 'next/server'
export async function GET() {
return NextResponse.json({
status: 'ok',
timestamp: new Date().toISOString(),
})
}
Best practice: Monitor BOTH the standalone health route AND the tRPC health procedure. They fail differently.
Advanced: Database Connectivity Check
Add a database ping to your tRPC health procedure:
import { db } from '~/server/db'
import { TRPCError } from '@trpc/server'
export const healthRouter = createTRPCRouter({
check: publicProcedure.query(async () => {
const checks: Record<string, 'ok' | 'error'> = {}
try {
await db.execute(sql`SELECT 1`)
checks.database = 'ok'
} catch {
checks.database = 'error'
}
const allHealthy = Object.values(checks).every(v => v === 'ok')
if (!allHealthy) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'Health check failed',
})
}
return { status: 'ok', checks }
}),
})
T3 Stack Monitoring Setup
For the full T3 Stack (Next.js + tRPC + Prisma + NextAuth), monitor these endpoints:
| Monitor | URL | Check |
|---|---|---|
| App uptime | https://your-app.com |
HTTP 200 |
| tRPC health | https://your-app.com/api/trpc/health.check |
JSON status:ok
|
| NextAuth session | https://your-app.com/api/auth/session |
HTTP 200 |
| API health (standalone) | https://your-app.com/api/health |
HTTP 200 |
This covers the full critical path a user would traverse when they visit your app.
Top comments (0)