8 february 2026

Use Zod to validate and document your environment variables

One of the most annoying errors in TypeScript is when your app crashes because you asserted the type of an environment variable, but forgot to set it.

This is an especially frequent issue with various serverless tools, which tend to have a lot of environments. Each of these environments comes with its own secrets that need to be typed manually into the UI, which is easy to forget.

Tired of such crashes, I decided to always validate environment variables, and found Zod to be a great solution, not only to this, but also to many other validation problems:

  1. Types are inferred from the validation result, not asserted by hand. Forgetting to set variable will result in error being thrown.
  2. This validation serves as documentation for environment variable usage. This type of documentation is much more useful than what’s written in .env.example or readme.md. Since you rely on the zod.parse output, you won’t forget to update it.
  3. Zod can perform transforms, which is useful because environment variables are always strings. For example, transform '1' to 1, or one,two to ['one','two'].

Here is an example of how to use Zod to validate environment variables:

import 'dotenv/config';
import { z } from 'zod';

const envSchema = z.object({
  BOT_TOKEN: z.string().min(1, 'BOT_TOKEN is not set'),
  OPENROUTER_API_KEY: z.string().min(1, 'OPENROUTER_API_KEY is not set'),
  WEBHOOK_URL: z.string().optional(),
});

export type EnvConfig = z.infer<typeof envSchema>;

export const env = envSchema.parse(process.env);

I describe the shape of process.env as a Zod schema, and then use this Zod schema to parse, and then export valid and typed env values, or throw if something is wrong.

Run this code as early as possible inside your app, or execute it as part of your CI or build script.


If you noticed a typo, or have a correction or question — write a comment to [email protected]