Skip to content

15.10 Modernization sequencing

บทนี้แปลง heat-map ในบท 14.9 ให้เป็น action plan ที่จัดลำดับเป็น Wave แต่ละ Wave ออกแบบให้ de-risk Wave ถัดไป และระบบไม่มีหน้าต่าง downtime แบบ big bang

ภาพรวม 4 Wave

Wave 0 ───► Wave 1 ───► Wave 2 ───► Wave 3
Stop-bleed   Stabilize   Strategic   Frontend
(2 สัปดาห์)   (3 เดือน)    (12 เดือน)   (15 เดือน)
Waveเป้าหมายระยะเวลาผลลัพธ์ที่ได้
0ลด Critical security/availability risk โดยไม่เปลี่ยน architecture1-2 สัปดาห์Critical debt ลดลง 7-10 รายการ
1ยกระดับ runtime และ dependency ที่ EOL1-3 เดือนNode 20 LTS, Apollo v4, React 18
2แยก bounded context ไป Go (backend)3-12 เดือนservice ย่อยที่ทันสมัย
3ย้าย frontend ไป Nuxt 36-15 เดือนfrontend ที่ทันสมัย

Wave 0 — Stop-the-bleed (สัปดาห์ที่ 0-2)

แก้ไขด่วนที่ไม่ต้องเปลี่ยน architecture ลดความเสี่ยง Critical ที่กำลังเกิด

ActionDebt IDEffortผู้รับผิดชอบแนะนำ
เปลี่ยน JWT_SECRET ให้ refuse to start ถ้า env ว่างSEC-430 นาทีbackend
ปิด playground/introspection ใน prodSEC-230 นาทีbackend
CORS allow-list บน centralize-apiSEC-530 นาทีbackend
ปิด syncModelToTable ใน prodCORR-61 ชั่วโมงbackend
ลบ phpMyAdmin จาก prod composePERF-71 ชั่วโมงops
เปลี่ยน qpdf execSync → execFileSEC-1, PERF-12-3 วันbackend
หมุนเวียน device key, ย้ายไป envSEC-31-2 วันbackend + ops
หมุนเวียน GCP SA key, ลบออกจาก repoSEC-111-2 วันops
ลบ typosquat packages (LEG-13) + commit centralize lockfileLEG-13, LEG-151 วันbackend
เพิ่ม engines.node ทุก package.jsonLEG-1830 นาทีbackend
ลบ axois typo + เพิ่ม axiosSEC-7, CORR-930 นาทีbackend
ลบ logging: ['query'] ใน centralize prodCORR-530 นาทีbackend
ลบ column ซ้ำใน hospital.jsCORR-730 นาทีbackend
ยกระดับ jsonwebtoken v8 → v9LEG-91 วันbackend
แก้ xlsx CVE (ใช้ exceljs หรือ CDN build)LEG-271 วันbackend
ลบ vtrc-web package-lock.json (เลือก yarn)LEG-1630 นาทีfrontend

ผลรวม Wave 0: effort ~10 วันทำงาน, ลด debt ได้ 15+ รายการ

เกณฑ์การตัดสินใจว่า Wave 0 เสร็จ:

  • [ ] ทุก Critical debt ในบท 14.1 ถูก mark ว่า mitigated
  • [ ] penetration test ใหม่ผ่าน
  • [ ] uptime monitor + alert ตั้งไว้ (Volume 13)

Wave 1 — Stabilize (เดือนที่ 1-3)

ยกระดับ runtime และ dependency ที่ EOL ให้ทันสมัย แต่ยังอยู่บน architecture เดิม

Backend

ActionDebt IDEffort
แปลง esm shim → native ESMLEG-22-3 สัปดาห์
ยกระดับ Node 12 → 20 LTSLEG-1(หลัง LEG-2)
Apollo Server v2 → v4LEG-31-2 สัปดาห์
เพิ่ม rate limit + structured logging + session indexed lookupSEC-10, LEG-24, PERF-31-2 สัปดาห์
แก้ RBAC inconsistency + test matrixCORR-41-2 สัปดาห์
เปลี่ยน ldapjs → ldaptsLEG-82-3 วัน
ยกระดับ redis v3 → v4LEG-122-3 วัน
ยกระดับ firebase-admin, googleapisLEG-292-3 วัน
แก้ transaction swallow patternCORR-21-2 วัน
เพิ่ม health endpoint ทุก service1-2 วัน

Frontend

ActionDebt IDEffort
เปลี่ยน Apollo default เป็น cache-and-networkPERF-21-2 วัน
รวม axios instancesLEG-201 สัปดาห์
ยกระดับ AntD v3 → v4 ใน webLEG-51 สัปดาห์
ยกระดับ jsonwebtoken, redis (เหมือน backend)LEG-9, LEG-12

Cross-cutting

ActionEffort
สร้าง CI/CD pipeline สำหรับ 3 repos ที่เหลือ1 สัปดาห์
ลบ _bk files 131 ไฟล์ + ตั้ง .gitignore + pre-commit1-2 วัน
ตั้ง logrotate + backup script (Volume 13)2-3 วัน
ตั้ง centralized logging (Loki + Grafana)1 สัปดาห์

ผลรวม Wave 1: ~3 เดือน, ลด debt ได้อีก 20+ รายการ

เกณฑ์การตัดสินใจว่า Wave 1 เสร็จ:

  • [ ] Node runtime ทุกตัวเป็น LTS ปัจจุบัน
  • [ ] ทุก service มี health endpoint
  • [ ] CI/CD ครอบคลุมทุก repo
  • [ ] centralized logging + monitoring + alerting ทำงาน

Wave 2 — Strategic (เดือนที่ 3-12)

เริ่มแยก bounded context ไป service ใหม่ที่ใช้ Go (Hexagonal/DDD) ทีละ context จากที่โดดเดี่ยวที่สุดก่อน

ลำดับการแยก bounded context

ลำดับBounded contextเหตุผลที่ทำก่อนเป้าหมาย
1document-renderer (PDF/Excel/qpdf)self-contained, แก้ SEC-1/PERF-1 root causeGo + chromedp + pdfcpu
2identity (auth, session, RBAC, device key)ปลดล็อก context อื่น, แก้ SEC-3/4, CORR-4Go + Casbin + Postgres
3payroll (slip, tax)read-mostly, ขอบเขตชัดGo + gqlgen
4time-attendancehigh-volume read, ได้ประโยชน์จาก cacheGo + Redis
5leavemulti-level workflow, ขอบเขตชัดGo + saga
6welfare (WDHospital)ซับซ้อนที่สุด (state machine 13 สถานะ, controller 3,179 LOC)Go + state machine package
7provident-fund, communication, organization, shared-kernelที่เหลือGo

โครงสร้างแต่ละ context

<service>/
├── cmd/                  # entrypoint (driving adapter)
├── internal/
│   ├── <context>/
│   │   ├── domain/       # entity, value object, domain service
│   │   ├── port/         # use-case interface
│   │   ├── adapter/      # db, redis, sftp, pdf, smtp
│   │   └── usecase/      # application service
├── migrations/           # forward-only migration
└── go.mod

Migration strategy แต่ละ context

  1. เขียน service ใหม่ใน Go คู่ขนาน
  2. ใช้ strangler pattern — route traffic บางส่วนไป service ใหม่ (feature flag)
  3. ค่อย ๆ เพิ่มสัดส่วน traffic
  4. เมื่อ service ใหม่ stable ลบ code เดิมจาก vtrc-api

เป้าหมาย Wave 2

  • [ ] bounded context 3 ตัวแรก (document-renderer, identity, payroll) live ใน production
  • [ ] vtrc-api เล็กลง 30-40%
  • [ ] Critical performance debt (PERF-1, PERF-6) หมดไป

Wave 3 — Frontend → Nuxt 3 (เดือนที่ 6-15)

เริ่มได้หลัง identity และ payroll service ใหม่ live (frontend มี API stable ใหม่)

ลำดับ

ลำดับActionEffort
1สร้าง Nuxt 3 shell + auth + routing2 สัปดาห์
2ย้าย feature ที่ใช้บ่อย (login, profile, payslip) ก่อน1-2 เดือน
3ย้าย feature ที่ซับซ้อน (leave, welfare)2-3 เดือน
4ย้าย backoffice2-3 เดือน

โครงสร้าง (Feature-Sliced Design)

apps/web/                    # แทน vtrc-web
└── src/
    ├── app/                 # global shell, providers
    ├── processes/           # routing strategies
    ├── pages/               # route-level composition
    ├── widgets/             # composite blocks
    ├── features/            # user actions
    ├── entities/            # domain slices
    │   └── <slice>/api/     # co-located gql operations
    └── shared/              # ui-kit, api, lib, config, i18n

เป้าหมาย Wave 3

  • [ ] vtrc-web และ vtrc-rc-backoffice ใช้งานบน Nuxt 3
  • [ ] React, Apollo Client v2, AntD legacy ไม่ใช้แล้ว
  • [ ] frontend bundle เล็กลง > 50%

สิ่งที่ต้องระวังในทุก Wave

  1. อย่า stop deployment นานเกินไป — ทุก Wave ต้อง deploy ต่อไปได้ระหว่าง migration
  2. รักษา backward compatibility — API เก่าต้องยังทำงานจนกว่า client ทุกตัวย้าย
  3. ทดสอบใน UAT ก่อนเสมอ — แต่ละWave ต้องมีช่วง UAT
  4. เก็บ runbook ให้ทันสมัย — Volume 13 ต้องอัปเดตตามการเปลี่ยนแปลง
  5. วัดผล — ตั้ง KPI เช่น "Critical debt ลดลง X รายการ" และ track ทุกเดือน

KPI ของแต่ละ Wave

WaveKPIเป้าหมาย
0Critical debt ที่ mitigated≥ 10 รายการ
1Node runtime เวอร์ชัน≥ 20 LTS ทุก service
1service ที่มี health endpoint5/5
2bounded context ที่แยกแล้ว≥ 3
2vtrc-api LOCลดลง 30%
3frontend บน Nuxt 32/2

สรุป

ลำดับนี้ออกแบบให้:

  • Wave 0 ลดความเสี่ยงทันที
  • Wave 1 ทำให้ foundation มั่นคง
  • Wave 2 ลดขนาด monolith ทีละส่วน
  • Wave 3 ยก frontend ใหม่ทั้งหมด

ทีมสามารถปรับลำดับได้ตามบริบท เช่น ถ้า frontend มี feature ใหม่ด่วน อาจเริ่ม Wave 3 ก่อน Wave 2 จบ

รายละเอียดเชิงลึกของแต่ละ Wave จะอยู่ใน Volume 15 (Modernization Plan)