Environment variable tách config khỏi code theo 12-factor app: config là bất cứ thứ gì đổi giữa các môi trường (dev/staging/prod).
bash
# .env
DATABASE_URL=postgresql://...
JWT_SECRET=...
NODE_ENV=developmentrequire('dotenv').config() nạp .env vào process.env và KHÔNG ghi đè biến đã có — production inject thẳng qua Docker/K8s/CI, không cần file .env. dotenv-safe đối chiếu với .env.example lúc khởi động và throw nếu thiếu biến, thay vì để undefined lọt qua.
Validate config bằng Zod để fail fast với thông báo rõ ràng:
ts
export const config = z.object({
DATABASE_URL: z.string().url(),
PORT: z.coerce.number().default(3000),
JWT_SECRET: z.string().min(32),
}).parse(process.env)Export một module config.ts đã có type thay vì rải process.env khắp nơi — dễ test và type-safe hơn.
Lưu ý: process.env.PORT luôn là string nên phải coerce sang number; và đừng commit .env — dùng .gitignore cùng .env.example làm template.