name: Config & Environment Conventions
description: Conventions for service configuration and environment variables: naming, precedence, validation at startup, secrets handling, environment detection, and documentation patterns
Config & Environment Conventions
Overview
มาตรฐานการจัดการ configuration และ environment variables ทุก service: naming, validation, defaults, และ secret handling ที่ทำให้ deploy ข้าม environments ได้อย่างมั่นใจ
Why This Matters
- Portability: Same code, different configs per env
- Safety: Validate config at startup, fail fast
- Security: Clear separation of secrets
- Debugging: รู้ว่า config มาจากไหน
Core Concepts
1. Environment Variable Naming
- รูปแบบ:
<APP>_<CATEGORY>_<NAME> (ทั้งหมด UPPER_SNAKE_CASE)
URL/URI ใช้ suffix เดียวกัน (APP_REDIS_URL), boolean ใช้ true|false
- แยก “config” กับ “secret” ชัดเจน (ดูข้อ 4)
- หลีกเลี่ยงชื่อกว้าง ๆ เช่น
TOKEN, KEY (ต้องบอกบริบท เช่น APP_STRIPE_SECRET_KEY)
2. Config Hierarchy
กำหนดลำดับความสำคัญชัดเจน และ document ไว้ในทุก service:
- Secret manager (Vault/AWS SM/GCP SM)
- Environment variables (runtime)
- Environment-specific file (
.env.production) (เฉพาะ local/staging ที่อนุญาต)
- Default
.env (เฉพาะ local)
- Code defaults (ปลอดภัย และไม่ใช่ production values)
3. Config Validation
- validate ตั้งแต่ startup (fail fast) ก่อนรับ traffic
- แยก
required vs optional ชัดเจน
- validate type/format/range (เช่น port, URL, enum)
- log เฉพาะ keys ที่โหลดสำเร็จ (ไม่ log ค่า secret)
4. Secret vs Config
- Secret: credentials, tokens, private keys, passwords, encryption keys → ต้องมาจาก secret manager และ rotate ได้
- Config: hostnames, timeouts, feature toggles, limits → environment variables/ไฟล์ config ได้
- หลีกเลี่ยงการผสม: อย่าเอา secret ลง
.env.example (ให้ใส่เป็นค่าว่าง + comment ว่า “from secret manager”)
5. Feature Flags Integration
- config ที่เปลี่ยน “ตอน runtime” (เช่น rollout %) → ใช้ feature flag system
- config ที่เป็น “deploy-time” (เช่น DB host, timeout) → ใช้ env vars
- หลีกเลี่ยง “config drift”: ทุก flag ต้องมี owner + cleanup date
6. Environment Detection
- มีตัวแปรเดียวสำหรับ env:
APP_ENV=development|staging|production|test
- หลีกเลี่ยง inference จาก
NODE_ENV เพียงอย่างเดียว (ใช้ร่วมได้ แต่ให้มี source-of-truth)
- gating behavior ที่อันตราย (debug endpoints, verbose logging) ต้องผูกกับ
APP_ENV
7. Config Documentation
- ทุก service ต้องมี
.env.example ที่ครบ keys และมีคำอธิบายสั้น ๆ
- ระบุ default/constraints เช่น
APP_HTTP_PORT=3000 (min/max ถ้ามี)
- ถ้ามี schema (Zod/JSON schema) ให้ link ในเอกสารของ service/README
8. Default Values
- defaults ต้อง “ปลอดภัย” (เช่น feature ปิด, rate limit conservative)
- ห้ามใส่ค่า production จริงเป็น default
- config สำคัญ (DB URL, secret keys) ควร required และบังคับให้ตั้งใน env/secret manager
Quick Start
import { z } from "zod";
const schema = z.object({
APP_ENV: z.enum(["development", "staging", "production", "test"]).default("development"),
APP_HTTP_PORT: z.coerce.number().int().min(1).max(65535).default(3000),
APP_DATABASE_URL: z.string().url(),
});
export type AppConfig = z.infer<typeof schema>;
export function loadConfig(env: Record<string, string | undefined> = process.env): AppConfig {
const result = schema.safeParse(env);
if (!result.success) {
throw new Error(`Invalid config: ${result.error.message}`);
}
return result.data;
}
Production Checklist
Naming Convention
# Format: <APP>_<CATEGORY>_<NAME>
# Database
APP_DB_HOST=localhost
APP_DB_PORT=5432
APP_DB_NAME=myapp
# External Services
APP_REDIS_URL=redis://localhost:6379
APP_STRIPE_API_URL=https://api.stripe.com
# Feature Flags
APP_FEATURE_NEW_CHECKOUT=true
# Secrets (loaded from secret manager)
APP_SECRET_DB_PASSWORD= # from Vault/AWS SM
APP_SECRET_API_KEY= # from Vault/AWS SM
Config Hierarchy
Priority (highest to lowest):
1. Secret Manager (Vault, AWS SM)
2. Environment Variables
3. Environment-specific file (.env.production)
4. Default .env file
5. Code defaults
Anti-patterns
- Hardcoded values: Config in code
- Secrets in .env: Committed to git
- No validation: Runtime failures
- Magic strings: Config keys scattered in code
- Implicit env: behavior เปลี่ยนตาม
NODE_ENV แบบคาดเดายาก
Integration Points
- Secret managers
- CI/CD pipelines
- Container orchestration
- Feature flag systems
Further Reading
1---2name: config-env-conventions3description: มาตรฐานการจัดการ configuration และ environment variables ทุก service: naming, validation, defaults, และ secret handling ที่ทำให้ deploy ข้าม environments ได้อย่างมั่นใจ4---5
6---
7name: Config & Environment Conventions
8description: Conventions for service configuration and environment variables: naming, precedence, validation at startup, secrets handling, environment detection, and documentation patterns
9---
10
11# Config & Environment Conventions
12
13## Overview
14
15มาตรฐานการจัดการ configuration และ environment variables ทุก service: naming, validation, defaults, และ secret handling ที่ทำให้ deploy ข้าม environments ได้อย่างมั่นใจ
16
17## Why This Matters
18
19- **Portability**: Same code, different configs per env
20- **Safety**: Validate config at startup, fail fast
21- **Security**: Clear separation of secrets
22- **Debugging**: รู้ว่า config มาจากไหน
23
24---
25
26## Core Concepts
27
28### 1. Environment Variable Naming
29
30- รูปแบบ: `<APP>_<CATEGORY>_<NAME>` (ทั้งหมด **UPPER_SNAKE_CASE**)
31- `URL`/`URI` ใช้ suffix เดียวกัน (`APP_REDIS_URL`), boolean ใช้ `true|false`
32- แยก “config” กับ “secret” ชัดเจน (ดูข้อ 4)
33- หลีกเลี่ยงชื่อกว้าง ๆ เช่น `TOKEN`, `KEY` (ต้องบอกบริบท เช่น `APP_STRIPE_SECRET_KEY`)
34
35### 2. Config Hierarchy
36
37กำหนดลำดับความสำคัญชัดเจน และ document ไว้ในทุก service:
38
391. Secret manager (Vault/AWS SM/GCP SM)
402. Environment variables (runtime)
413. Environment-specific file (`.env.production`) (เฉพาะ local/staging ที่อนุญาต)
424. Default `.env` (เฉพาะ local)
435. Code defaults (ปลอดภัย และไม่ใช่ production values)
44
45### 3. Config Validation
46
47- validate ตั้งแต่ startup (fail fast) ก่อนรับ traffic
48- แยก `required` vs `optional` ชัดเจน
49- validate type/format/range (เช่น port, URL, enum)
50- log เฉพาะ keys ที่โหลดสำเร็จ (ไม่ log ค่า secret)
51
52### 4. Secret vs Config
53
54- **Secret**: credentials, tokens, private keys, passwords, encryption keys → ต้องมาจาก secret manager และ rotate ได้
55- **Config**: hostnames, timeouts, feature toggles, limits → environment variables/ไฟล์ config ได้
56- หลีกเลี่ยงการผสม: อย่าเอา secret ลง `.env.example` (ให้ใส่เป็นค่าว่าง + comment ว่า “from secret manager”)
57
58### 5. Feature Flags Integration
59
60- config ที่เปลี่ยน “ตอน runtime” (เช่น rollout %) → ใช้ feature flag system
61- config ที่เป็น “deploy-time” (เช่น DB host, timeout) → ใช้ env vars
62- หลีกเลี่ยง “config drift”: ทุก flag ต้องมี owner + cleanup date
63
64### 6. Environment Detection
65
66- มีตัวแปรเดียวสำหรับ env: `APP_ENV=development|staging|production|test`
67- หลีกเลี่ยง inference จาก `NODE_ENV` เพียงอย่างเดียว (ใช้ร่วมได้ แต่ให้มี source-of-truth)
68- gating behavior ที่อันตราย (debug endpoints, verbose logging) ต้องผูกกับ `APP_ENV`
69
70### 7. Config Documentation
71
72- ทุก service ต้องมี `.env.example` ที่ครบ keys และมีคำอธิบายสั้น ๆ
73- ระบุ default/constraints เช่น `APP_HTTP_PORT=3000` (min/max ถ้ามี)
74- ถ้ามี schema (Zod/JSON schema) ให้ link ในเอกสารของ service/README
75
76### 8. Default Values
77
78- defaults ต้อง “ปลอดภัย” (เช่น feature ปิด, rate limit conservative)
79- ห้ามใส่ค่า production จริงเป็น default
80- config สำคัญ (DB URL, secret keys) ควร required และบังคับให้ตั้งใน env/secret manager
81
82## Quick Start
83
84```typescript
85import { z } from "zod";
86
87const schema = z.object({
88 APP_ENV: z.enum(["development", "staging", "production", "test"]).default("development"),
89 APP_HTTP_PORT: z.coerce.number().int().min(1).max(65535).default(3000),
90 APP_DATABASE_URL: z.string().url(),
91});
92
93export type AppConfig = z.infer<typeof schema>;
94
95export function loadConfig(env: Record<string, string | undefined> = process.env): AppConfig {
96 const result = schema.safeParse(env);
97 if (!result.success) {
98 throw new Error(`Invalid config: ${result.error.message}`);
99 }
100 return result.data;
101}
102```
103
104## Production Checklist
105
106- [ ] All env vars documented in .env.example
107- [ ] Config validated at startup
108- [ ] Secrets not in .env files
109- [ ] Defaults are safe (not production values)
110- [ ] Required vs optional clearly marked
111- [ ] Config changes don't require code changes
112
113## Naming Convention
114
115```bash
116# Format: <APP>_<CATEGORY>_<NAME>
117
118# Database
119APP_DB_HOST=localhost
120APP_DB_PORT=5432
121APP_DB_NAME=myapp
122
123# External Services
124APP_REDIS_URL=redis://localhost:6379
125APP_STRIPE_API_URL=https://api.stripe.com
126
127# Feature Flags
128APP_FEATURE_NEW_CHECKOUT=true
129
130# Secrets (loaded from secret manager)
131APP_SECRET_DB_PASSWORD= # from Vault/AWS SM
132APP_SECRET_API_KEY= # from Vault/AWS SM
133```
134
135## Config Hierarchy
136
137```
138Priority (highest to lowest):
1391. Secret Manager (Vault, AWS SM)
1402. Environment Variables
1413. Environment-specific file (.env.production)
1424. Default .env file
1435. Code defaults
144```
145
146## Anti-patterns
147
1481. **Hardcoded values**: Config in code
1492. **Secrets in .env**: Committed to git
1503. **No validation**: Runtime failures
1514. **Magic strings**: Config keys scattered in code
1525. **Implicit env**: behavior เปลี่ยนตาม `NODE_ENV` แบบคาดเดายาก
153
154## Integration Points
155
156- Secret managers
157- CI/CD pipelines
158- Container orchestration
159- Feature flag systems
160
161## Further Reading
162
163- [12-Factor App: Config](https://12factor.net/config)
164- [Node.js Config Best Practices](https://github.com/goldbergyoni/nodebestpractices#1-project-structure-practices)