Store all environment-specific configuration (API URLs, database connections, feature flags) in environment variables, never in source code. Hardcoded config means your staging code talks to production databases, your API keys are in git history, and deploying to a new environment requires code changes.
Hardcoded configuration creates environment coupling — the same code cannot run in development, staging, and production without modification. This leads to staging tests hitting production databases, API keys leaking into git history, and deployment to new environments requiring code changes instead of configuration changes.
BeforeMerge scans your pull requests against this rule and 3+ others. Get actionable feedback before code ships.
Environment-specific configuration (database URLs, API endpoints, feature flags, credentials) changes between development, staging, and production. If this configuration is hardcoded in source code, you face three problems:
Environment coupling: The same code cannot run in different environments without modification. Developers must remember to change URLs before deploying, and forgetting means staging code talks to production databases.
Secret exposure: Hardcoded credentials end up in version control, accessible to every developer, CI runner, and backup system. See the "never-commit-secrets" rule for the full impact.
Deployment friction: Deploying to a new environment (a new region, a new client, a disaster recovery setup) requires code changes instead of configuration changes, turning a 5-minute deploy into a multi-day project.
All environment-specific configuration must come from environment variables. Source code must contain zero hardcoded URLs, connection strings, API keys, or environment-specific feature flags.
// lib/config.ts — hardcoded configuration
export const config = {
apiUrl: "https://api.production.example.com",
dbUrl: "postgres://admin:pass@prod-db.example.com:5432/mydb",
stripeKey: "sk_live_abc123",
enableBetaFeature: true,
};// lib/config.ts — reads from environment variables
import { z } from "zod";
const envSchema = z.object({
API_URL: z.string().url(),
DATABASE_URL: z.string(),
STRIPE_SECRET_KEY: z.string(),
ENABLE_BETA_FEATURE: z.coerce.boolean().default(false),
});
export const config = envSchema.parse(process.env);# .env.local (not committed to git)
API_URL=http://localhost:3000/api
DATABASE_URL=postgres://dev:dev@localhost:5432/mydb_dev
STRIPE_SECRET_KEY=sk_test_xyz789
ENABLE_BETA_FEATURE=falseSearch for hardcoded URLs, connection strings, and credentials:
grep -rn 'https://.*\.production\|postgres://\|mysql://\|mongodb://' --include="*.ts" --include="*.tsx" lib/ app/.env.example to the repository with placeholder values (no real secrets).env files are in .gitignore