Environment Variables & Configuration with Zod
process.env is where an Express app's real configuration lives, database URLs, API keys, ports, but TypeScript types every property on process.env as string | undefined, and nothing stops a typo'd or missing variable from reaching production. Validate it with Zod the same way you validate a request body.
z.coerce.number() converts the incoming string (everything in process.env is a string) to a number before validating it, exactly what an environment variable needs, PORT arrives as the string "3000", not the number 3000. Calling EnvSchema.parse(process.env) once, at startup, means a missing or malformed DATABASE_URL crashes the app immediately with a clear error, instead of failing mysteriously the first time a database query runs, minutes or hours later.
A typed config module
Importing config instead of reading process.env directly anywhere else in the codebase means every other file gets a fully typed, already-validated object, no string | undefined and no repeated validation.
WARNING
Never commit real secrets (database passwords, API keys) to source control, even in a .env.example file, real .env files belong in .gitignore. Zod validates the shape of your configuration, it doesn't protect a secret that's already been checked in.