KB-6FF9

S115 MySQL to PostgreSQL Migration Report

3 min read Revision 1

S115 MySQL to PostgreSQL Migration — Final Report

Date: 2026-03-13 Status: COMPLETE PRs: #496 (infra), #497 (deploy fix), #498 (docs)

Root Cause of Deploy #165 Failure

  1. Nginx stale DNS (502): When docker compose restart nuxt ran, the nuxt container got a new IP. Nginx had cached the old IP in its upstream resolver. The health check curl https://vps.incomexsaigoncorp.vn/ hit nginx which tried the stale IP -> 502 -> rollback triggered.

  2. PG_PASSWORD missing: The new docker-compose.yml uses ${PG_PASSWORD} for the postgres service, but the VPS .env only had DB_PASSWORD. Docker Compose warned about the blank variable.

Fixes Applied

VPS (direct)

  • Added PG_PASSWORD to /opt/incomex/docker/.env
  • Ran nginx -s reload to clear stale DNS

PR #496 — feat: migrate Directus from MySQL to PostgreSQL

  • infra/docker/docker-compose.yml: MySQL service replaced with PostgreSQL 16
  • infra/docker/.env.example: MySQL vars replaced with PG vars
  • dot/configs/directus.env.template: DB_CLIENT=pg, port 5432
  • docker-compose.local.yml: Added migration note
  • scripts/0047c_*.sh (3 files): Added DEPRECATED headers

PR #497 — fix: reload nginx after service restart

  • Added nginx -s reload after service restarts in both deploy modes
  • Prevents future stale DNS 502 errors during deploys

PR #498 — docs: MySQL retirement notes

  • Added S115 amendment notes to 5 architecture docs

Verification

Check Result
Deploy GREEN Deploy to VPS succeeded (run 23041779873)
DB_CLIENT=pg on VPS Confirmed
MySQL container STOPPED incomex-mysql Exited (0)
Directus healthy status ok
API reads data meta_catalog CAT-000 catalog
v_registry_counts works CAT-000=20 CAT-001=20 CAT-002=4
Site loads HTTP 200
Docs updated 5 files with S115 amendment notes

Architecture After Migration

  • Database: PostgreSQL 16 (container: postgres)
  • Directus: 11.5 with DB_CLIENT=pg DB_HOST=postgres DB_PORT=5432
  • MySQL: RETIRED container stopped
  • PG features: auto-code triggers CHECK constraints refresh_registry_counts() v7.0.0

Conclusion

MySQL RETIRED. PostgreSQL 16 = DB duy nhat cho Directus tren VPS.