Skip to main content

Production readiness guide

This checklist outlines the exact technical steps required to move the Payofy platform from local Docker containers to a live, production-grade environment.

1. Domain names and SSL termination​

Currently, the Nginx gateway listens only on HTTP port 80. Production traffic must use HTTPS on port 443 with valid SSL certificates.

Actions required:​

  • Configure DNS A records pointing your domains to your VPS public IP:
    • api.payofy.si -> Backend REST API
    • admin.payofy.si -> Staff Ops Console
    • portal.payofy.si -> Partner & Merchant Portal
    • docs.payofy.si -> Developer Documentation
    • payofy.si -> Apex marketing and portal landing
  • Add Certbot / Let's Encrypt automated certificate renewal, or place Cloudflare / AWS Application Load Balancer in front of the server for SSL termination.
  • Configure HTTP to HTTPS redirection (301 status).

2. Secrets and environment configuration​

Never run production with default credentials.

Actions required:​

  • Update .env on the VPS with cryptographically random passwords:
    • POSTGRES_PASSWORD: Use a random 32-character string.
    • REDIS_PASSWORD: Protect Redis with password authentication.
    • JWT_SECRET: Secret key used for signing API tokens.
  • Add Kurv live production credentials:
    • KURV_BASE_URL: Set to the live Kurv production gateway URL.
    • KURV_API_KEY: Production API key issued by Kurv.
    • KURV_WEBHOOK_SECRET: Production secret for signing webhook events.
  • Restrict access to .env using file permissions:
    chmod 600 .env

3. Webhook verification and idempotency​

Payment webhooks directly alter financial records and ledger accounts.

Actions required:​

  • Verify that every inbound Kurv webhook request has its HMAC signature verified before processing.
  • Reject requests with invalid signatures with HTTP 401.
  • Verify idempotency keys on every transaction. If a webhook arrives twice, ignore the second request without creating duplicate ledger entries.
  • Test failure scenarios: dropped webhooks, network timeouts, and replay attempts.

4. Automated database backups​

A VPS local disk can fail. You need offsite database backups before processing actual money.

Actions required:​

  • Set up an automated daily pg_dump cron job.
  • Encrypt and upload backup dumps to external object storage (AWS S3, Cloudflare R2, or Backblaze B2).
  • Retain backups for at least 30 days.
  • Test restoring from a database backup dump to verify recovery procedures.

5. Background queue reliability​

BullMQ handles critical asynchronous jobs like merchant dunning, webhook delivery, and ledger reconciliation.

Actions required:​

  • Enable Redis persistence (AOF or RDB snapshots) so jobs are not lost during Redis restarts.
  • Configure job retry limits with exponential backoff.
  • Implement a dead-letter queue (DLQ) for failed payment jobs.
  • Set up alerts if queue depth exceeds normal thresholds.

6. Monitoring, logging, and error tracking​

You must know about errors before your customers do.

Actions required:​

  • Install Sentry or a similar error tracking tool in both the backend API and frontend apps.
  • Set up external uptime monitoring (Uptime Kuma, Better Stack, or Pingdom) checking https://api.payofy.si/v1/health every minute.
  • Configure Discord or Slack alerts for container failures or high server CPU / memory usage.

7. Automated CI/CD pipeline​

Manual server SSH updates are error-prone.

Actions required:​

  • Create a GitHub Actions workflow that automatically runs:
    • Type checking (pnpm typecheck)
    • Test suites (pnpm test)
    • Production build (pnpm build)
  • Configure automatic container image building and deployment to your VPS on merges to main.