External Configuration vs Hard Coded Validation
External configuration beats hard-coded validation for any rule that changes faster than your release cycle. Hard-coding wins only for invariants that are part of your domain's identity.
The short answer
External Configuration over Hard Coded Validation for most cases. Validation rules are business policy, and business policy changes on a schedule that has nothing to do with your deploy pipeline.
- Pick External Configuration if the rule is policy that changes — price thresholds, allowed countries, feature gates, regex for new ID formats, anything a product manager will ask you to tweak
- Pick Hard Coded Validation if the rule is a true domain invariant — a non-null primary key, a positive quantity, a state-machine transition that defines what your object IS
- Also consider: A hybrid: hard-code structural invariants that protect data integrity, externalize the policy layer on top. Don't put both in the same if-statement and call it a day.
— Nice Pick, opinionated tool recommendations
What actually changes here
Validation isn't one thing. There's structural validation — this field must be a non-null integer — and there's policy validation — orders over $10,000 need approval, we don't ship to these three countries. Structural rules are part of your data model and almost never change. Policy rules change constantly, decided by people who don't read code and don't care about your sprint. The entire debate is really about which bucket a given rule falls into. Hard-coding a non-null check is fine; nobody files a ticket to allow null IDs. Hard-coding the list of embargoed countries is how you end up doing an emergency deploy at 11pm because legal added one. Most teams lose because they treat all validation as the structural kind, then act shocked when the policy kind demands a release for a one-line change.
Where external config wins
External configuration — env vars, a feature-flag service, a database table, a JSON schema fetched at boot — decouples the rule's lifecycle from your binary's. Change the max upload size without a build. Roll out a stricter password policy to 10% of users. Let support flip a threshold without paging an engineer. This is the whole reason LaunchDarkly, OPA, and JSON Schema exist. The cost is real and people undersell it: you now have config that can be wrong, drift between environments, and fail to load. An empty config file silently disabling all validation is a genuine production incident. You need defaults, schema-validation of the config itself, and audit logs. But 'the rule changed and we shipped it in 30 seconds' beats 'the rule changed and we cut a release' every single time the rule actually changes — which it will.
Where hard-coding earns its keep
Hard-coded validation is honest about one thing: the rule lives next to the code that depends on it, type-checked, testable, version-controlled, reviewable. No runtime fetch, no 'why is staging rejecting valid input,' no config-drift mystery. For invariants — a positive quantity, a valid state transition, an email that's structurally an email — this is correct and externalizing it is cargo-cult flexibility. You will never A/B test whether a primary key can be null. The failure mode is using hard-coding as a synonym for 'I didn't want to think about it.' Buried magic numbers, a regex four call-stacks deep, business thresholds inlined across six services that now disagree. That's not hard-coding, that's a scavenger hunt. Hard-coding is a deliberate choice for stable invariants, not the default you reach for because wiring up config felt like effort.
The hybrid that actually ships
The right architecture isn't a religion, it's a split. Hard-code the structural invariants — the rules that, if violated, mean your data is corrupt regardless of business context. Externalize the policy layer — anything a non-engineer might reasonably want to change. Keep them in separate, named layers so nobody confuses 'quantity must be positive' with 'orders over $5k need a second approver.' Validate your external config against a schema at startup and fail loud if it's malformed — a missing config should crash boot, never silently pass everything. Centralize policy rules in one place so six services can't disagree about the embargo list. The teams that suffer are the ones with no layer at all: thresholds smeared through controllers, half in env vars, half inlined, none documented. Pick the seam on purpose. The seam is the whole decision.
Quick Comparison
| Factor | External Configuration | Hard Coded Validation |
|---|---|---|
| Change without redeploy | Yes — flip config, rule updates live | No — requires a build and release |
| Type safety & testability | Weaker — config can be malformed at runtime | Strong — compiled, reviewed, unit-tested |
| Best fit | Policy rules that change on a business schedule | Structural invariants that define the domain |
| Silent failure risk | Real — empty/bad config can disable all checks | Low — rule can't vanish without a code change |
| Operational agility | High — support/PM can change rules safely | Low — every tweak is an engineering task |
The Verdict
Use External Configuration if: The rule is policy that changes — price thresholds, allowed countries, feature gates, regex for new ID formats, anything a product manager will ask you to tweak.
Use Hard Coded Validation if: The rule is a true domain invariant — a non-null primary key, a positive quantity, a state-machine transition that defines what your object IS.
Consider: A hybrid: hard-code structural invariants that protect data integrity, externalize the policy layer on top. Don't put both in the same if-statement and call it a day.
External Configuration vs Hard Coded Validation: FAQ
Is External Configuration or Hard Coded Validation better?
External Configuration is the Nice Pick. Validation rules are business policy, and business policy changes on a schedule that has nothing to do with your deploy pipeline. Externalize it or pay in hotfixes.
When should you use External Configuration?
The rule is policy that changes — price thresholds, allowed countries, feature gates, regex for new ID formats, anything a product manager will ask you to tweak.
When should you use Hard Coded Validation?
The rule is a true domain invariant — a non-null primary key, a positive quantity, a state-machine transition that defines what your object IS.
What's the main difference between External Configuration and Hard Coded Validation?
External configuration beats hard-coded validation for any rule that changes faster than your release cycle. Hard-coding wins only for invariants that are part of your domain's identity.
How do External Configuration and Hard Coded Validation compare on change without redeploy?
External Configuration: Yes — flip config, rule updates live. Hard Coded Validation: No — requires a build and release. External Configuration wins here.
Are there alternatives to consider beyond External Configuration and Hard Coded Validation?
A hybrid: hard-code structural invariants that protect data integrity, externalize the policy layer on top. Don't put both in the same if-statement and call it a day.
Validation rules are business policy, and business policy changes on a schedule that has nothing to do with your deploy pipeline. Externalize it or pay in hotfixes.
Related Comparisons
Disagree? nice@nicepick.dev