Làm sao để ứng dụng của bạn dễ triển khai, dễ scale, và vận hành mượt mà trên Kubernetes, Docker, hoặc cloud? Câu trả lời nằm ở 12-Factor App – một phương pháp thiết kế ứng dụng được Heroku đề xuất và ngày nay đã trở thành tiêu chuẩn ngầm cho kiến trúc cloud-native và microservices.
1. Codebase – Một codebase duy nhất
“One codebase tracked in revision control, many deploys”
- Mỗi app chỉ nên có một repo duy nhất, không tách code thành nhiều nhánh riêng biệt cho từng môi trường.
- Triển khai nhiều môi trường (dev, test, prod) dựa trên cùng một source code, chỉ khác cấu hình.
💡 Gợi ý: Dùng Git và CI/CD để kiểm soát mọi thay đổi.
2. Dependencies – Khai báo phụ thuộc rõ ràng
“Explicitly declare and isolate dependencies”
- Ứng dụng không nên phụ thuộc vào các thư viện cài sẵn trên hệ điều hành.
- Cần khai báo tất cả dependencies thông qua công cụ như pom.xml, package.json, requirements.txt.
💡 Gợi ý: Dùng Docker để đảm bảo môi trường build luôn đồng nhất.
3. Config – Tách cấu hình khỏi mã nguồn
“Store config in environment variables”
- Tất cả cấu hình như API key, DB URL, secret… phải nằm ngoài code và được truyền qua biến môi trường (ENV VARS).
- Tránh hardcode bất kỳ thông tin nhạy cảm nào vào repo.
💡 Gợi ý: Dùng Vault hoặc Secret Manager để quản lý biến môi trường an toàn.
4. Backing Services – Dịch vụ gắn ngoài
“Treat backing services as attached resources”
- DB, cache, MQ, object storage… đều được xem là dịch vụ gắn ngoài.
- Có thể thay đổi các dịch vụ này bằng config, mà không ảnh hưởng đến code.
💡 Gợi ý: Tạo interface chuẩn cho các service adapter.
5. Build, Release, Run – Tách biệt ba giai đoạn
“Strictly separate build and run stages”
- Build: Compile mã và đóng gói (VD: tạo Docker image)
- Release: Gắn cấu hình vào build → bản chính thức
- Run: Chạy thực tế với process độc lập
💡 Gợi ý: Triển khai CI/CD theo pipeline build → release → deploy.
6. Processes – Chạy ứng dụng dạng stateless
“Execute the app as one or more stateless processes”
- App không nên giữ trạng thái (state) trong RAM hay local file.
- Tất cả trạng thái cần lưu trong DB, Redis, v.v.
💡 Gợi ý: Dùng JWT thay vì session RAM để xác thực người dùng.
7. Port Binding – Tự mở port và lắng nghe
“Export services via port binding”
- Ứng dụng nên tự mở port để phục vụ, không phụ thuộc vào reverse proxy.
- Phù hợp với container/Kubernetes vì mọi app là một dịch vụ độc lập.
💡 Gợi ý: Spring Boot/Tomcat mở port 8080 là ví dụ điển hình.
8. Concurrency – Scale theo process
“Scale out via the process model”
- Scale app bằng cách tăng số lượng instance/process, không cần viết code xử lý đa luồng.
- Dễ dàng dùng Kubernetes HPA để scale ngang.
💡 Gợi ý: Thiết kế app stateless để dễ scale.
9. Disposability – Khởi động nhanh, dừng gọn
“Fast startup and graceful shutdown”
- App nên khởi động nhanh, và shutdown sạch (close connection, flush log…).
- Hỗ trợ scale nhanh, rolling update, và resiliency.
💡 Gợi ý: Bắt tín hiệu SIGTERM trong container để xử lý graceful shutdown.
10. Dev/prod parity – Đồng nhất môi trường
“Keep development, staging, and production as similar as possible”
- Môi trường dev, test, staging, prod cần giống nhau tối đa: cùng DB loại, cùng cách deploy, cùng image Docker.
- Tránh dùng SQLite local trong dev mà dùng Postgres ở prod.
💡 Gợi ý: Dockerize mọi thứ, kể cả trong local dev.
11. Logs – Ghi log ra stdout
“Treat logs as event streams”
- App không nên quản lý file log. Thay vào đó, ghi log ra stdout để hệ thống ngoài (Fluentd, ELK, Splunk…) thu thập.
- Log nên được stream, phân tích, alert theo thời gian thực.
💡 Gợi ý: Dùng logback/log4j + cấu hình JSON + stdout.
12. Admin processes – Tác vụ quản trị ngắn hạn
“Run admin/management tasks as one-off processes”
- Các lệnh như migrate DB, import dữ liệu… nên chạy tách biệt, như một process riêng.
- Không nên tích hợp vào luồng chính.
💡 Gợi ý: Dùng kubectl exec hoặc Job trong Kubernetes để chạy admin task.