What is it
Hardcoded means writing fixed values directly in source code, instead of getting them from an external source like:
- Environment variables
- Configuration files
- Database
- User input
It’s one of the most common bad practices in software development.
Accepted spellings
- Hard-coded (hyphenated)
- Hardcoded (one word)
- Hard coded (two words)
Example: The Phone Number Nobody Can Change
Hardcoded code (BAD)
// ❌ BAD: Hardcoded phone number
function sendSMS(message) {
const phone = "+1-555-123-4567"; // 😱 Hardcoded
smsService.send(phone, message);
}
// ❌ BAD: Hardcoded URL
function getUsers() {
const url = "https://api.mycompany.com/users"; // 😱 Hardcoded
return fetch(url);
}
// ❌ BAD: Hardcoded credentials (DANGEROUS)
function connectDB() {
const password = "admin123"; // 🚨 NEVER do this
return db.connect("admin", password);
}
Correct code (GOOD)
// ✅ GOOD: From environment variable
function sendSMS(message) {
const phone = process.env.SMS_PHONE_NUMBER;
smsService.send(phone, message);
}
// ✅ GOOD: From configuration
function getUsers() {
const url = config.api.usersEndpoint;
return fetch(url);
}
// ✅ GOOD: Credentials from environment
function connectDB() {
const password = process.env.DB_PASSWORD;
return db.connect(process.env.DB_USER, password);
}
Why it’s a problem
| Problem | Consequence |
|---|---|
| Hard to change | Must modify code, recompile, and redeploy |
| Insecure | Credentials exposed in repositories |
| Not scalable | Different values for dev/staging/production |
| Hard to maintain | Values scattered throughout code |
| Breaks tests | Can’t easily use test values |
Why it matters for your business
If you buy or evaluate software, this is not a technical detail: it is what turns a trivial change into an expensive one.
- A one-minute change takes days. Raising a price, changing the notification email or a tax rate should be editing a field. Hard-coded, it means changing code, testing it and shipping a new release.
- It ties you to whoever wrote it. If the only way to change something is to touch the code, you depend on that provider, their schedule and their rate.
- It is a security risk. Passwords and keys written into the code end up copied into every backup and onto every machine holding the repository.
- It makes every environment costlier. Testing in a staging environment means duplicating and editing code instead of changing a setting.
The question worth asking before signing off on a delivery: what can I change myself without calling the provider? If the answer is “nothing”, every future adjustment arrives as a quote.
It is one of the most common forms of technical debt and a standing check in our legacy system modernization work.
Real-World Example: The Pizzeria and its Prices
Imagine you have an ordering system for your pizzeria.
Hardcoded approach (guaranteed problems)
# pricing.py - ❌ BAD
def calculate_total(pizzas, drinks):
pizza_price = 15.00 # 😱 Hardcoded
drink_price = 3.50 # 😱 Hardcoded
tax_rate = 0.08 # 😱 Hardcoded
subtotal = (pizzas * pizza_price) + (drinks * drink_price)
return subtotal * (1 + tax_rate)
Problems:
- Tax rate changes → Must find all “0.08” in code
- Pizza promotion at $12 → Modify code, test, deploy
- Branch in another state with different prices and taxes → You have to duplicate or fork the code
Configuration approach (flexible)
# config.py
import os
PRICES = {
"pizza": float(os.getenv("PIZZA_PRICE", 15.00)),
"drink": float(os.getenv("DRINK_PRICE", 3.50)),
"tax_rate": float(os.getenv("TAX_RATE", 0.08)),
}
# pricing.py - ✅ GOOD
from config import PRICES
def calculate_total(pizzas, drinks):
subtotal = (pizzas * PRICES["pizza"]) + (drinks * PRICES["drink"])
return subtotal * (1 + PRICES["tax_rate"])
Benefits:
- Change prices without touching code (just restart or redeploy with different configuration)
- Different prices per environment (dev/prod)
- For values that change often, such as promotions, storing them in a database is ideal
When hardcoding IS acceptable
Sometimes fixed values make sense:
// ✅ Mathematical constants
const PI = 3.14159265359;
// ✅ Values that NEVER change
const DAYS_IN_WEEK = 7;
const HOURS_IN_DAY = 24;
// ✅ Default values (with override option)
const TIMEOUT = config.timeout || 5000; // Default: 5 seconds
// ✅ Enums or fixed states
const STATES = {
PENDING: "pending",
COMPLETED: "completed",
CANCELLED: "cancelled"
};
How to identify hardcoded code
Warning signs in your code:
🚨 Strings with full URLs
🚨 Magic numbers (42, 1000, 3600)
🚨 Credentials or tokens
🚨 Absolute file paths
🚨 Email addresses
🚨 Server names
🚨 Specific ports
How to fix it
1. Environment variables
# .env (don't commit it: add it to .gitignore)
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
API_KEY=sk-1234567890
MAX_CONNECTIONS=100
2. Configuration files
// config.json
{
"api": {
"baseUrl": "https://api.example.com",
"timeout": 5000
}
}
3. Named constants
// constants.js
export const MAX_RETRY_ATTEMPTS = 3;
export const SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
Related terms
- Refactoring - Process of improving code without changing its behavior
- Environment Variables - Variables configured outside of code
- Configuration Management - Application configuration management
Remember: If you ever think “this will never change,” it probably will. Better to use configuration from the start.