Skip to main content

Overview

This guide covers production deployment strategies for VulnTrack, including database configuration, scaling, monitoring, and performance optimization.

Pre-Deployment Checklist

1

Environment Configuration

  • Set NODE_ENV=production
  • Configure secure NEXTAUTH_SECRET (32+ characters)
  • Use production database with SSL
  • Enable HTTPS/TLS
  • Configure proper CORS settings
  • Set up error monitoring
2

Database Setup

  • Use managed PostgreSQL service or dedicated server
  • Enable connection pooling
  • Configure automated backups
  • Set up replica for read scaling (optional)
  • Enable SSL/TLS for connections
3

Security Hardening

  • Review Security Guide
  • Configure firewall rules
  • Set up rate limiting
  • Enable audit logging
  • Configure RBAC policies
4

Monitoring & Logging

  • Set up application monitoring
  • Configure log aggregation
  • Set up alerts for critical errors
  • Monitor database performance
  • Track API response times

Database Configuration

Use a managed database service for production:
DATABASE_URL="postgresql://username:[email protected]:5432/vulntrack?sslmode=require&connection_limit=20"

Connection Pooling

For optimal performance, use connection pooling:
prisma/schema.prisma
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  directUrl = env("DIRECT_URL") // For migrations
}
.env
# Pooled connection (for queries)
DATABASE_URL="postgresql://user:pass@host:5432/db?pgbouncer=true&connection_limit=10"

# Direct connection (for migrations)
DIRECT_URL="postgresql://user:pass@host:5432/db"
Set connection_limit to match your application’s concurrency needs. Start with 10-20 and adjust based on monitoring.

Database Migrations

For production, use Prisma migrations instead of db push:
1

Generate migration

npx prisma migrate dev --name init
2

Review migration SQL

Check the generated SQL in prisma/migrations/ directory.
3

Deploy to production

npx prisma migrate deploy
Never use prisma db push in production as it may result in data loss. Always use migrations for schema changes.

Backup Strategy

Configure automated backups with your database provider:
  • Frequency: Daily full backups + continuous WAL archiving
  • Retention: 30 days for daily, 7 days for point-in-time
  • Testing: Regularly test restore procedures
# Manual backup example
pg_dump -h your-db.example.com -U vulntrack \
  -F c -b -v \
  -f backup_$(date +%Y%m%d).dump \
  vulntrack
Enable PITR for critical deployments:
  • Configure WAL archiving
  • Store archives in S3/GCS
  • Test recovery procedures monthly
# Restore to test database
pg_restore -h test-db.example.com -U vulntrack \
  -d vulntrack_test \
  --clean --if-exists \
  backup_20260303.dump

# Verify data integrity
psql -h test-db.example.com -U vulntrack -d vulntrack_test \
  -c "SELECT COUNT(*) FROM \"User\"; SELECT COUNT(*) FROM \"Vulnerability\";"

Application Deployment

Build Configuration

Update package.json build script for production:
package.json
{
  "scripts": {
    "build": "npx prisma generate && next build",
    "start": "next start",
    "migrate:deploy": "npx prisma migrate deploy"
  }
}
Remove prisma db push --accept-data-loss from production builds. Use migrations instead.

Next.js Configuration

The application includes production-ready security headers:
next.config.mjs
const nextConfig = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Strict-Transport-Security',
            value: 'max-age=63072000; includeSubDomains; preload'
          },
          {
            key: 'X-Frame-Options',
            value: 'SAMEORIGIN'
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff'
          },
          {
            key: 'Referrer-Policy',
            value: 'origin-when-cross-origin'
          },
          {
            key: 'Content-Security-Policy',
            value: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline';"
          }
        ]
      }
    ]
  }
};

Deployment Platforms

Vercel

# Install Vercel CLI
npm i -g vercel

# Deploy
vercel --prod
Configure in vercel.json:
{
  "buildCommand": "prisma generate && next build",
  "env": {
    "DATABASE_URL": "@database-url"
  }
}

Docker

See Docker Deployment guide.For production:
  • Use docker-compose with restart policies
  • Configure health checks
  • Set resource limits
  • Use secrets management

Kubernetes

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vulntrack
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: vulntrack
        image: vulntrack:latest
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"

AWS ECS

Deploy using ECS Fargate:
  • Use task definitions with secrets from AWS Secrets Manager
  • Configure ALB for load balancing
  • Enable CloudWatch logs
  • Set up auto-scaling policies

Scaling Strategies

Horizontal Scaling

VulnTrack is stateless and can be horizontally scaled:
1

Load Balancer

Deploy multiple instances behind a load balancer:
  • Use health check endpoint: /api/health
  • Enable sticky sessions for WebSocket support (if added)
  • Configure SSL/TLS termination at load balancer
2

Database Read Replicas

For read-heavy workloads:
// Use read replica for queries
const readReplica = new PrismaClient({
  datasources: {
    db: {
      url: process.env.DATABASE_READ_URL
    }
  }
});
3

Caching

Implement caching for frequently accessed data:
  • Use Redis for session storage
  • Cache vulnerability statistics
  • Implement HTTP caching headers

Performance Optimization

// Use select to limit fields
const users = await prisma.user.findMany({
  select: {
    id: true,
    name: true,
    email: true,
    role: true
  },
  where: { teamId }
});

// Use indexes for frequent queries
// Add to schema.prisma:
// @@index([teamId, status])
  • Enable output: ‘standalone’ in next.config.js
  • Use Image optimization for logos/avatars
  • Implement route-level code splitting
  • Enable compression (gzip/brotli)
Enable Prisma query logging:
const prisma = new PrismaClient({
  log: [
    { level: 'query', emit: 'event' },
    { level: 'warn', emit: 'stdout' },
    { level: 'error', emit: 'stdout' }
  ]
});

prisma.$on('query', (e) => {
  if (e.duration > 1000) {
    console.warn('Slow query:', e.query, e.duration);
  }
});

Monitoring & Observability

Application Monitoring

// src/lib/sentry.ts
import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1,
  beforeSend(event) {
    // Filter sensitive data
    if (event.request) {
      delete event.request.cookies;
    }
    return event;
  }
});

Health Checks

Implement comprehensive health checks:
app/api/health/route.ts
import { prisma } from '@/lib/prisma';

export async function GET() {
  try {
    // Check database connection
    await prisma.$queryRaw`SELECT 1`;
    
    return Response.json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      database: 'connected'
    });
  } catch (error) {
    return Response.json(
      {
        status: 'unhealthy',
        timestamp: new Date().toISOString(),
        database: 'disconnected',
        error: error.message
      },
      { status: 503 }
    );
  }
}

Metrics to Monitor

MetricDescriptionAlert Threshold
Response TimeAPI endpoint latency> 1000ms
Error Rate5xx responses> 1%
Database ConnectionsActive connections> 80% of limit
CPU UsageContainer CPU> 80%
Memory UsageContainer memory> 85%
Disk SpaceDatabase storage> 80%

Environment Variables

Production Environment

.env.production
# Application
NODE_ENV=production
NEXTAUTH_URL=https://vulntrack.example.com
NEXTAUTH_SECRET=<generate-with-openssl-rand-base64-32>

# Database
DATABASE_URL=postgresql://user:[email protected]:5432/vulntrack?sslmode=require&connection_limit=20
DIRECT_URL=postgresql://user:[email protected]:5432/vulntrack?sslmode=require

# Monitoring (Optional)
SENTRY_DSN=https://[email protected]/xxx
DATADOG_API_KEY=xxx

# Logging
LOG_LEVEL=info
Store secrets in a secure secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.) rather than plain environment variables.

Deployment Workflow

1

Pre-deployment Testing

# Run tests
npm run test

# Check types
npm run lint

# Build locally
npm run build
2

Database Migration

# Deploy migrations
npx prisma migrate deploy

# Verify schema
npx prisma db pull
3

Application Deployment

# Build and tag image
docker build -t vulntrack:v1.0.0 .

# Push to registry
docker push registry.example.com/vulntrack:v1.0.0

# Deploy (example with kubectl)
kubectl set image deployment/vulntrack \
  vulntrack=registry.example.com/vulntrack:v1.0.0
4

Post-deployment Verification

# Check health
curl https://vulntrack.example.com/api/health

# Monitor logs
kubectl logs -f deployment/vulntrack

# Test critical paths
# - User login
# - Vulnerability creation
# - Dashboard loading

Zero-Downtime Deployments

For production environments, implement rolling updates:
kubernetes-deployment.yaml
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  minReadySeconds: 10
  template:
    spec:
      containers:
      - name: vulntrack
        livenessProbe:
          httpGet:
            path: /api/health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /api/health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5

Disaster Recovery

1

Document Recovery Procedures

Maintain runbooks for:
  • Database restoration
  • Application rollback
  • DNS failover
  • Data center migration
2

Regular DR Drills

Test recovery procedures quarterly:
  • Restore from backup to test environment
  • Verify data integrity
  • Measure recovery time objective (RTO)
3

Backup Infrastructure

Consider multi-region deployment:
  • Active-passive for cost efficiency
  • Active-active for mission-critical deployments

Troubleshooting

Common Production Issues

Symptoms: “Too many connections” errorsSolutions:
  • Reduce connection_limit in DATABASE_URL
  • Implement connection pooling (PgBouncer)
  • Scale database instance
Symptoms: Increasing memory usage over timeSolutions:
  • Use Node.js heap snapshots
  • Check for unclosed Prisma clients
  • Implement memory limits and auto-restart policies
Symptoms: High response times, database CPU spikesSolutions:
  • Enable query logging
  • Add indexes to frequently queried fields
  • Use database query analyzer

Next Steps

Security Hardening

Implement security best practices

Docker Deployment

Container deployment guide

Build docs developers (and LLMs) love