Skip to content

Add database connection health check to backend /api/health endpoint #187

@Calebux

Description

@Calebux

Description

The backend has an /api/admin/health endpoint but it does not verify that the database connection is actually working. The endpoint can return { status: 'ok' } even when the Supabase connection is broken, making health checks useless for deployment verification.

Current State

// Health endpoint likely returns static 'ok' without checking dependencies
app.get('/api/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date() });
});

Fix: Comprehensive dependency health check

Checked Dependencies

  1. Supabase DB — run a lightweight ping query
  2. Email service — verify SMTP connection (not send)
  3. Blockchain RPC (if configured) — verify reachability
  4. Scheduler — verify cron jobs are running
  5. EventListener — verify polling is active

Implementation

router.get('/health', async (req, res) => {
  const checks = await Promise.allSettled([
    checkDatabase(),
    checkEmailService(),
    checkBlockchainRpc(),
  ]);

  const [db, email, blockchain] = checks.map(c => 
    c.status === 'fulfilled' ? { status: 'healthy' } : { status: 'unhealthy', error: c.reason.message }
  );

  const isHealthy = db.status === 'healthy';  // DB is critical; others are degraded
  
  res.status(isHealthy ? 200 : 503).json({
    status: isHealthy ? 'healthy' : 'degraded',
    timestamp: new Date().toISOString(),
    version: process.env.npm_package_version,
    dependencies: { database: db, email, blockchain },
    uptime: process.uptime(),
  });
});

async function checkDatabase(): Promise<void> {
  const { error } = await supabase.from('profiles').select('id').limit(1);
  if (error) throw new Error(`Database check failed: ${error.message}`);
}

Response Example

{
  "status": "degraded",
  "timestamp": "2025-03-15T10:00:00Z",
  "version": "1.2.3",
  "dependencies": {
    "database": { "status": "healthy", "latencyMs": 23 },
    "email": { "status": "unhealthy", "error": "SMTP connection refused" },
    "blockchain": { "status": "healthy", "lastLedger": 12345678 }
  },
  "uptime": 86400
}

Public vs Admin Health

  • GET /api/health — public, returns only { status, timestamp } (no internals)
  • GET /api/admin/health — admin-only, returns full dependency breakdown

Acceptance Criteria

  • /api/health pings database and returns 503 if DB is down
  • Admin health endpoint shows all dependency statuses with latency
  • Response includes version from package.json
  • Vercel post-deploy check can use /api/health to verify deployment
  • Latency of each dependency check included in response

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions