Environment Config Manager
Expert in 12-factor configuration management, feature flags, and environment-specific config across dev, staging, and production.
Activation Triggers
Activate on: "environment variables", "ConfigMap", "feature flags", "12-factor config", "dotenv setup", "config per environment", "runtime configuration", "config validation", "environment parity"
NOT for: Secret storage → secret-management-expert | IaC provisioning → terraform-module-builder | CI/CD variables → github-actions-pipeline-builder
Quick Start
- Separate config from code — no hardcoded URLs, ports, or feature toggles in source
- Define config schema — typed validation with defaults (zod, envalid, convict)
- Layer environments — base config overridden by environment-specific values
- Implement feature flags — runtime toggleable features without deployment
- Validate on startup — fail fast if required config is missing or invalid
Core Capabilities
| Domain |
Technologies |
| Validation |
zod, envalid, @t3-oss/env-nextjs, convict, joi |
| Feature Flags |
LaunchDarkly, Unleash, Flagsmith, Statsig, simple JSON flags |
| K8s Config |
ConfigMap, ExternalSecret, Kustomize overlays |
| Local Dev |
dotenv, direnv, 1Password CLI (op run), docker-compose env |
| Runtime Config |
etcd, Consul KV, AWS AppConfig, Firebase Remote Config |
Architecture Patterns
Typed Config Validation (TypeScript)
// config/env.ts — fail fast on invalid config
import { z } from 'zod';
const envSchema = z.object({
NODE_ENV: z.enum(['development', 'staging', 'production']),
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url().optional(),
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
FEATURE_NEW_CHECKOUT: z.coerce.boolean().default(false),
API_RATE_LIMIT: z.coerce.number().default(100),
});
export type Env = z.infer<typeof envSchema>;
// Parse and validate — throws on startup if invalid
export const env = envSchema.parse(process.env);
Environment Layering
.env # Base defaults (committed, no secrets)
.env.development # Dev overrides (committed)
.env.staging # Staging overrides (committed, no secrets)
.env.production # Production overrides (committed, no secrets)
.env.local # Local overrides (gitignored, may have secrets)
Loading order (later overrides earlier):
.env → .env.{NODE_ENV} → .env.local
Secrets come from secret store, NOT .env files:
DATABASE_URL → AWS Secrets Manager / Vault
API_KEY → External Secrets Operator
Feature Flag Architecture
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Client │ │ Flag Store │ │ Admin UI │
│ SDK/hook │───▶│ (Unleash/ │◀───│ Toggle flags │
│ │ │ LaunchDarkly)│ │ per env │
└──────────────┘ └──────────────┘ └──────────────┘
Evaluation: user context + flag rules → boolean/variant
- Percentage rollout: 10% of users see new feature
- User targeting: beta users see new feature
- Environment: enabled in staging, disabled in production
- Kill switch: instantly disable without deployment
Anti-Patterns
- Config in code — hardcoded
localhost:5432 or if (env === 'production') scattered across files. Centralize all config in one validated module.
- Secrets in .env files committed to Git — even example files leak secret formats. Use
.env.example with placeholder descriptions, not values.
- No config validation — trusting
process.env.PORT is a valid number. Validate and coerce all config at startup with a schema library.
- Feature flags as permanent config — flags accumulate and become tech debt. Set expiration dates and clean up old flags quarterly.
- Environment-specific code paths —
if (process.env.NODE_ENV === 'production') for business logic. Use feature flags instead; environment should only affect infrastructure config.
Quality Checklist
[ ] All config loaded from environment variables (12-factor compliant)
[ ] Config schema validated on application startup (fail fast)
[ ] .env.example documents all required variables with descriptions
[ ] No secrets in committed .env files
[ ] .env.local in .gitignore
[ ] Feature flags have owner, description, and expiration date
[ ] Dev/staging/production parity maintained (same config keys)
[ ] Config changes do not require code deployment
[ ] Default values sensible for development (zero-config local setup)
[ ] ConfigMaps and Secrets separated in Kubernetes
[ ] Feature flag cleanup tracked in backlog
[ ] Runtime config changes logged and auditable
1---2name: environment-config-manager3description: Environment configuration manager for 12-factor config, feature flags, and multi-environment management. Activate on: environment variables, ConfigMap, feature flags, 12-factor config, dotenv management, config per environment, runtime config. NOT for: secret storage (use secret-management-expert), IaC provisioning (use terraform-module-builder), CI/CD variables (use github-actions-pipeline-builder).4license: Apache-2.05---6
7# Environment Config Manager
8
9Expert in 12-factor configuration management, feature flags, and environment-specific config across dev, staging, and production.
10
11## Activation Triggers
12
13**Activate on:** "environment variables", "ConfigMap", "feature flags", "12-factor config", "dotenv setup", "config per environment", "runtime configuration", "config validation", "environment parity"
14
15**NOT for:** Secret storage → `secret-management-expert` | IaC provisioning → `terraform-module-builder` | CI/CD variables → `github-actions-pipeline-builder`
16
17## Quick Start
18
191. **Separate config from code** — no hardcoded URLs, ports, or feature toggles in source
202. **Define config schema** — typed validation with defaults (zod, envalid, convict)
213. **Layer environments** — base config overridden by environment-specific values
224. **Implement feature flags** — runtime toggleable features without deployment
235. **Validate on startup** — fail fast if required config is missing or invalid
24
25## Core Capabilities
26
27| Domain | Technologies |
28|--------|-------------|
29| **Validation** | zod, envalid, @t3-oss/env-nextjs, convict, joi |
30| **Feature Flags** | LaunchDarkly, Unleash, Flagsmith, Statsig, simple JSON flags |
31| **K8s Config** | ConfigMap, ExternalSecret, Kustomize overlays |
32| **Local Dev** | dotenv, direnv, 1Password CLI (`op run`), docker-compose env |
33| **Runtime Config** | etcd, Consul KV, AWS AppConfig, Firebase Remote Config |
34
35## Architecture Patterns
36
37### Typed Config Validation (TypeScript)
38
39```typescript
40// config/env.ts — fail fast on invalid config
41import { z } from 'zod';
42
43const envSchema = z.object({
44 NODE_ENV: z.enum(['development', 'staging', 'production']),
45 PORT: z.coerce.number().default(3000),
46 DATABASE_URL: z.string().url(),
47 REDIS_URL: z.string().url().optional(),
48 LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
49 FEATURE_NEW_CHECKOUT: z.coerce.boolean().default(false),
50 API_RATE_LIMIT: z.coerce.number().default(100),
51});
52
53export type Env = z.infer<typeof envSchema>;
54
55// Parse and validate — throws on startup if invalid
56export const env = envSchema.parse(process.env);
57```
58
59### Environment Layering
60
61```
62.env # Base defaults (committed, no secrets)
63.env.development # Dev overrides (committed)
64.env.staging # Staging overrides (committed, no secrets)
65.env.production # Production overrides (committed, no secrets)
66.env.local # Local overrides (gitignored, may have secrets)
67
68Loading order (later overrides earlier):
69 .env → .env.{NODE_ENV} → .env.local
70
71Secrets come from secret store, NOT .env files:
72 DATABASE_URL → AWS Secrets Manager / Vault
73 API_KEY → External Secrets Operator
74```
75
76### Feature Flag Architecture
77
78```
79┌──────────────┐ ┌──────────────┐ ┌──────────────┐
80│ Client │ │ Flag Store │ │ Admin UI │
81│ SDK/hook │───▶│ (Unleash/ │◀───│ Toggle flags │
82│ │ │ LaunchDarkly)│ │ per env │
83└──────────────┘ └──────────────┘ └──────────────┘
84
85Evaluation: user context + flag rules → boolean/variant
86 - Percentage rollout: 10% of users see new feature
87 - User targeting: beta users see new feature
88 - Environment: enabled in staging, disabled in production
89 - Kill switch: instantly disable without deployment
90```
91
92## Anti-Patterns
93
941. **Config in code** — hardcoded `localhost:5432` or `if (env === 'production')` scattered across files. Centralize all config in one validated module.
952. **Secrets in .env files committed to Git** — even example files leak secret formats. Use `.env.example` with placeholder descriptions, not values.
963. **No config validation** — trusting `process.env.PORT` is a valid number. Validate and coerce all config at startup with a schema library.
974. **Feature flags as permanent config** — flags accumulate and become tech debt. Set expiration dates and clean up old flags quarterly.
985. **Environment-specific code paths** — `if (process.env.NODE_ENV === 'production')` for business logic. Use feature flags instead; environment should only affect infrastructure config.
99
100## Quality Checklist
101
102```
103[ ] All config loaded from environment variables (12-factor compliant)
104[ ] Config schema validated on application startup (fail fast)
105[ ] .env.example documents all required variables with descriptions
106[ ] No secrets in committed .env files
107[ ] .env.local in .gitignore
108[ ] Feature flags have owner, description, and expiration date
109[ ] Dev/staging/production parity maintained (same config keys)
110[ ] Config changes do not require code deployment
111[ ] Default values sensible for development (zero-config local setup)
112[ ] ConfigMaps and Secrets separated in Kubernetes
113[ ] Feature flag cleanup tracked in backlog
114[ ] Runtime config changes logged and auditable
115```