Environment Validation for AI Applications: T3 Env, API Keys and Safe Deployments
An Invalid environment variables error is a deployment guard, not an obstacle to bypass. In an AI application, typed configuration can prevent a preview build from calling production models, a gateway from starting without provider credentials, or an agent from receiving permissions intended for another environment.
Model configuration as a contract
Validate values that change application behavior:
- provider API-key presence;
- provider and model identifiers;
- gateway and callback URLs;
- timeout and retry limits;
- environment name;
- feature flags and evaluation thresholds;
- public versus server-only values.
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
OPENAI_API_KEY: z.string().min(1),
AI_MODEL: z.string().min(1),
AI_REQUEST_TIMEOUT_MS: z.coerce.number().int().positive(),
APP_ENV: z.enum(["development", "preview", "production"]),
},
runtimeEnv: {
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
AI_MODEL: process.env.AI_MODEL,
AI_REQUEST_TIMEOUT_MS: process.env.AI_REQUEST_TIMEOUT_MS,
APP_ENV: process.env.APP_ENV,
},
});
The schema validates shape and presence. It should never log or expose secret values.
Keep server secrets off the client
Only explicitly public variables belong in a client schema or public prefix. A provider key must remain server-side even if frontend code needs the selected model name. Treat the bundler boundary as a security boundary and inspect built client assets when configuration changes.
The environment variables foundation explains secret injection and rotation. AI Security covers the wider credential model.
Preview and production drift
Preview deployments should use isolated keys, quotas, callbacks, datasets, and storage. Validation can require environment-specific fields, but avoid one schema full of optional values that lets every environment start in a half-configured state.
Use separate deployment configuration and test:
- preview cannot reach production data;
- production does not use test keys or model aliases;
- callback and OAuth origins match the environment;
- model/provider fallbacks are intentional;
- missing optional integrations fail closed where security requires it.
Build-time versus runtime validation
A static build may not have production runtime secrets, while a server process does. Decide deliberately which values must exist during build and which are injected when the workload starts. Do not skip all validation simply to make CI green.
After deployment, make a small authenticated inference request and verify the configured provider/model without returning secrets. Connect that gate to AI Testing & Evaluation and AI Deployment & Hosting.
Safe diagnosis
- Read the exact failing key and validation rule.
- Confirm the expected environment and loading boundary.
- Check the secret store contains the key nameβwithout printing its value.
- Verify the schema and runtime mapping agree.
- Rebuild using the same deployment context.
- Smoke-test provider, model, callbacks, and failure behavior.
Typed configuration belongs in the AI Application Architecture because it turns hidden deployment assumptions into a reviewable contract.